Problema in GCC / C ++ 17 con classe modello di modello


10

Considera i 2 sovraccarichi seguenti

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

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

Il primo funziona per le classi regolari, mentre il secondo per i modelli non istanziati. Per esempio:

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

Ora considera la seguente funzione modello:

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

In GCC dà un errore per la risoluzione ambigua del sovraccarico, mentre Clang compila. È interessante notare che la seconda chiamata a test () non produce errori (anche in GCC). Inoltre, se rimuovo la template<typename U>cosa sopra templfun, gcc smette di lamentarsi.

È un bug con GCC o è un codice illegale?

Risposte:


4

GCC è sbagliato; struct Aè un'entità templata ma chiaramente non è un modello (in quanto non inizia con una templateparola chiave), quindi non c'è ambiguità.

Per confermare, possiamo rinominare il parametro type per vedere che G ++ sta tentando di usare il sovraccarico template-template.

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

Uscita G ++: ( collegamento 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() {
      |      ^~~~

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

Si noti che i tipi locali non erano ammessi come argomenti modello prima di C ++ 11 (vedere C ++ 03 § 14.3.1.2), in modo che ciò potesse spiegare la complessità dell'implementazione di G ++.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.