Ich verstehe nicht, was das Problem ist: entweder in meinem Code oder im Compiler (weniger möglich). Es gibt einen Code wie diesen:
#include <iostream>
#include <type_traits>
#include <set>
template<typename T, typename = void>
struct TestA: std::false_type {};
template<typename T>
struct TestA<T, std::void_t<typename T::reverse_iterator>> : std::true_type {};
template<typename T>
struct TestA<T, std::void_t<typename T::dummy_iterator>> : std::true_type {};
int main()
{
std::cout << TestA<std::set<int>>::value;
}
Sowohl GCC als auch MSVC kompilieren es. Ich habe es auf Godbolt mit verschiedenen Versionen von GCC und MSVC 17 (lokal) und 19 getestet. Hier ist ein Link: https://godbolt.org/z/Enfm6L .
Aber Clang kompiliert es nicht und gibt einen Fehler aus:
redefinition of `'TestA<T, std::void_t<typename T::dummy_iterator> >'`
Und ich bin interessiert - vielleicht gibt es einen Teil des Standards, in dem dieser Code falsch ist, oder vielleicht etwas anderes.
Antworten:
Dies hängt sehr wahrscheinlich mit CWG 1558 zusammen .
Es ist ein Fehler, der seitdem behoben wurde, aber wenn die von Ihnen verwendete Version von Clang das Update noch nicht implementiert, werden möglicherweise beide Spezialisierungen als einfache Definition des zweiten Arguments betrachtet
void
und nicht als Spiel für den gesamten Substitutionsfehler. Die Problemumgehung besteht darin, keinen einfachen Alias zu verwendenstd::void_t
, sondern eine etwas komplexere VersionFür eine Klassenvorlage (wofür der Alias jetzt steht) wird der Substitutionsfehler definiert. Wenn Sie dies in Ihr Beispiel einfügen, wird Clang https://godbolt.org/z/VnkwsM beschwichtigt .
quelle
enable_if
withstd::disjunction
(oder einer