Problem in GCC / C ++ 17 mit Vorlagenvorlagenklasse

10

Betrachten Sie die 2 folgenden Überlastungen

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

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

Der erste funktioniert für reguläre Klassen, während der zweite für Vorlagen funktioniert, die nicht instanziiert sind. Zum Beispiel:

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

Betrachten Sie nun die folgende Vorlagenfunktion:

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

In GCC gibt es einen Fehler für die mehrdeutige Überlastungsauflösung, während Clang kompiliert. Interessanterweise führt der zweite Aufruf von test () nicht zu Fehlern (auch nicht in GCC). Wenn ich das template<typename U>Ding über Templfun entferne, hört gcc außerdem auf, sich zu beschweren.

Ist das ein Fehler mit GCC oder ist es illegaler Code?

Marieddu
quelle

Antworten:

4

GCC ist falsch; struct Aist eine Entität mit Vorlagen, aber eindeutig keine Vorlage (da sie nicht mit einem templateSchlüsselwort beginnt ), sodass keine Mehrdeutigkeit besteht.

Zur Bestätigung können wir den Typparameter umbenennen, um festzustellen, dass G ++ versucht, die Template-Template-Überladung zu verwenden.

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 ++ Ausgabe: ( Link zu 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() {
      |      ^~~~

Offensichtlich ist " candidate: 'bool test() [with Y = templfun()::A]'" ein Schwindel.

Beachten Sie, dass lokale Typen vor C ++ 11 nicht als Vorlagenargumente zulässig waren (siehe C ++ 03 § 14.3.1.2), um die Komplexität der G ++ - Implementierung zu erklären.

Rustyx
quelle