https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78489
Bug ID: 78489 Summary: Subsitution failure does not happen in lexical order for SFINAE in NTTP. Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: eric at efcs dot ca Target Milestone: --- When substitution failure occurs in the declaration of a NTTP GCC will incorrectly continue to perform substitution on later template parameters. This is incorrect since substitution should occur in lexical order. Note that this does not occur when the substitution happens in the declaration of a type template parameter. Reproducer: // g++ -std=c++1z test.cpp template <bool Pred, class T> struct enable_if { typedef T type; }; template <class T> struct enable_if<false, T> {}; template <int Idx> struct blows_up { static_assert(Idx != Idx, ""); }; template <int Idx, // substitution should fail here typename enable_if<Idx != Idx, int>::type = 0, // GCC evaluates this statement class = typename blows_up<Idx>::type > void Foo() {} template <int Idx, // Substitution correctly fails here. class = typename enable_if<Idx != Idx, int>::type, class = typename blows_up<Idx>::type // OK. Not evaluated > constexpr void Bar() {} // Check the constructor in as SFINAE context template <int I> constexpr auto test(int) -> decltype((Foo<I>(), true)) { return true; } template <int> constexpr bool test(long) { return false; } template <int I> constexpr auto test_bar(int) -> decltype((Bar<I>(), true)) { return true; } template <int> constexpr bool test_bar(long) { return false; } static_assert(!test<3>(0), ""); // Blows up static_assert(!test_bar<4>(0), ""); // OK.