Problema no GCC / C ++ 17 com classe de modelo de modelo


10

Considere as 2 seguintes sobrecargas

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

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

O primeiro trabalha para classes regulares, enquanto o segundo trabalha para modelos que não são instanciados. Por exemplo:

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

Agora considere a seguinte função de modelo:

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

No GCC, ocorre um erro para a resolução ambígua de sobrecarga, enquanto Clang compila. Curiosamente, a segunda chamada para test () não produz erros (mesmo no GCC). Além disso, se eu remover a template<typename U>coisa em cima do templfun, o gcc para de reclamar.

Isso é um bug do GCC ou é um código ilegal?

Respostas:


4

O GCC está errado; struct Aé uma entidade de modelo, mas claramente não é um modelo (como não começa com uma templatepalavra - chave), portanto, não há ambiguidade.

Para confirmar, podemos renomear o parâmetro type para ver se o G ++ está tentando usar a sobrecarga de modelo-modelo.

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

Saída G ++: ( link para 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]'" é falso.

Observe que tipos locais não eram permitidos como argumentos de modelo anteriores ao C ++ 11 (consulte C ++ 03 § 14.3.1.2), de modo que isso pudesse explicar a complexidade da implementação do G ++.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.