Проблема в GCC / C ++ 17 з класом шаблону шаблонів


10

Розглянемо 2 наступні перевантаження

template<typename T>
bool test() {
    return true;
}

template<template<typename ...> class T>
bool test() {
    return false;
}

Перший працює для звичайних занять, а другий - для шаблонів, які не є інстанційними. Наприклад:

    std::cout<<test<int>()<<std::endl; <-- this yields 1
    std::cout<<test<std::list>()<<std::endl; <--this yields 0

Тепер розглянемо наступну функцію шаблону:

template<typename U>
bool templfun(){
    struct A{
        bool f(){
            return test<A>(); // <-- this gives an error
        }
    };
    return test<A>();  // <-- this is ok
}

У GCC він дає помилку за неоднозначну роздільну здатність перевантаження, тоді як Кланг компілює. Цікаво, що другий виклик тестувати () не призводить до помилок (навіть у GCC). Більше того, якщо я template<typename U>видаляю річ поверх templfun, gcc перестає скаржитися.

Це помилка з GCC чи це незаконний код?

Відповіді:


4

GCC помилковий; struct Aце шаблонна сутність, але явно не шаблон (оскільки вона не починається з templateключового слова), тому неоднозначності немає.

Для підтвердження ми можемо перейменувати параметр типу, щоб побачити, що G ++ намагається використовувати перевантаження шаблону шаблону.

template <typename X>
bool test() {
    return true;
}

template <template <typename...> class Y>
bool test() {
    return false;
}

template <typename U>
bool templfun() {
    struct A {
        bool f() {
            return test<A>(); // <-- this gives an error
        }
    };
    return test<A>(); // <-- this is ok
}

bool run() {
    return templfun<int>();
}

Вихід G ++: ( посилання на godbolt )

<source>:15:27: error: call of overloaded 'test<templfun() [with U = int]::A>()' is ambiguous
   15 |             return test<A>(); // <-- this gives an error
      |                    ~~~~~~~^~

<source>:2:6: note: candidate: 'bool test() [with X = templfun() [with U = int]::A]'
    2 | bool test() {
      |      ^~~~

<source>:7:6: note: candidate: 'bool test() [with Y = templfun()::A]'
    7 | bool test() {
      |      ^~~~

Очевидно, що " candidate: 'bool test() [with Y = templfun()::A]'" є хибним.

Зауважте, що локальні типи не були дозволені як аргументи шаблону до C ++ 11 (див. C ++ 03 § 14.3.1.2), щоб це могло пояснити складність реалізації G ++.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.