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.

Reply via email to