This question already has an answer here:
libstdc++'s implementation of std::experimental::optional
uses a SFINAE technique that seems to work with gcc, but not with clang.
I've reduced it to the following minimal example:
// Standard enable_if class
template <bool> struct enable_if {};
template <> struct enable_if<true> { typedef int type; };
// An example trait
template <typename> struct trait { static const bool value = true; };
// Overload to call if the trait is false
template<typename T, typename enable_if<!trait<T>::value>::type...>
void foo(T);
// Overload to call if the trait is true
template<typename T, typename enable_if<trait<T>::value>::type...>
void foo(T);
// Call site
void bar() {
foo(0);
}
This compiles with gcc, but not with clang. Clang's error is:
test.cpp:18:5: error: call to 'foo' is ambiguous
foo(0);
^~~
test.cpp:11:6: note: candidate function [with T = int, $1 = <>]
void foo(T);
^
test.cpp:14:6: note: candidate function [with T = int, $1 = <>]
void foo(T);
^
Clearly, gcc is discarding the first overload as a candidate because it encounters a substitution failure while subtituting T = int
into typename enable_if<!trait<T>::value>::type
.
Clang, on the other hand, seems to skip performing that substitution, perhaps because it realizes that there are zero template arguments bound to that parameter pack. As a result, it doesn't encounter a substitution failure, and the first overload remains viable.
Who is right?
Aucun commentaire:
Enregistrer un commentaire