Problema en GCC / C ++ 17 con la clase de plantilla de plantilla

10

Considere las 2 siguientes sobrecargas

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

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

El primero funciona para clases regulares, mientras que el segundo funciona para plantillas que no se instancian. Por ejemplo:

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

Ahora considere la siguiente función de plantilla:

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

En GCC da un error para la resolución de sobrecarga ambigua, mientras que Clang compila. Curiosamente, la segunda llamada a test () no produce errores (incluso en GCC). Además, si template<typename U>elimino la cosa encima de templfun, gcc deja de quejarse.

¿Es esto un error con GCC o es un código ilegal?

Marieddu
fuente

Respuestas:

4

GCC está mal; struct Aes una entidad con plantilla pero claramente no es una plantilla (ya que no comienza con una templatepalabra clave), por lo que no hay ambigüedad.

Para confirmar, podemos cambiar el nombre del parámetro de tipo para ver que G ++ está intentando usar la sobrecarga de plantilla-plantilla.

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>();
}

Salida de G ++: ( enlace a 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() {
      |      ^~~~

Claramente " candidate: 'bool test() [with Y = templfun()::A]'" es falso.

Tenga en cuenta que los tipos locales no estaban permitidos como argumentos de plantilla antes de C ++ 11 (consulte C ++ 03 § 14.3.1.2), por lo que podría explicar la complejidad de la implementación de G ++.

rustyx
fuente