https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87366
Bug ID: 87366 Summary: SFINAE trait as template parameter causes incorrect application of trait to other areas Product: gcc Version: 8.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: sudgylacmoe at gmail dot com Target Milestone: --- Created attachment 44727 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44727&action=edit Compiler output when trying to compile the complete code snippet This code should be accepted (and both clang and msvc accept it according to godbolt), but gcc does not, on every version that I tested (7, 8, and trunk): namespace std { template <typename T, typename U> struct is_same {static constexpr bool value = false;}; template <typename T> struct is_same<T, T> {static constexpr bool value = true;}; template <bool, typename T = void> struct enable_if {}; template <typename T> struct enable_if<true, T> {using type = T;}; template <typename T, typename U> constexpr bool is_same_v = is_same<T, U>::value; template <bool B, typename T = void> using enable_if_t = typename enable_if<B, T>::type; } struct A {}; struct B {}; template <typename T> struct wrapper {}; template <typename T, typename = std::enable_if_t<std::is_same_v<T, A>>> using ok_t = T; template <typename T> void not_even_called(wrapper<const ok_t<T>&> a); template <typename T> int called(wrapper<const T&> a); void test(wrapper<const B&>& val) { called(val); } GCC fails to compile with the following error message: test.cpp: In function ‘void test(wrapper<const B&>&)’: test.cpp:23:15: error: no matching function for call to ‘called(wrapper<const B&>&)’ called(val); ^ test.cpp:19:27: note: candidate: ‘template<class T> int called(wrapper<ok_t<T>&>)’ template <typename T> int called(wrapper<const T&> a); ^~~~~~ test.cpp:19:27: note: template argument deduction/substitution failed: test.cpp: In substitution of ‘template<class T> int called(wrapper<ok_t<T>&>) [with T = B]’: test.cpp:23:15: required from here test.cpp:19:27: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’ As you can see, the SFINAE trait ok_t from not_even_called got applied to the parameter in called. Removing not_even_called makes the code compile, and swapping the declaration of called and not_even_called makes the code compile (and then you can even call not_even_called with a wrapper<const B&>, which should fail). Removing the wrapper makes it compile, and moving the enable_if directly into the wrapper makes it compile as well. In addition, making ok_t work for struct B instead of struct A makes it compile. I'm guessing what is happening is that for some reason gcc thinks that wrapper<ok_t<T>> is the same as wrapper<T> and starts applying whatever it saw to the first occurrence to all future occurrences of the type. I have attached the compiler output when run with -v trying to compile the code I posted above.