[Bug c++/87464] Gcc reports hard error instead of SFINAE out the related method

redi at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Sun Jan 2 11:25:16 GMT 2022


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87464

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|normal                      |enhancement
   Last reconfirmed|                            |2022-01-02
             Status|UNCONFIRMED                 |NEW
     Ever confirmed|0                           |1

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Reduced:

template<bool, typename T> struct enable_if { };
template<typename T> struct enable_if<true, T> { using type = T; };
template<typename T> struct is_const { static constexpr bool value = false; };
template<typename T> struct is_const<const T> { static constexpr bool value =
true; };

template<typename T>
struct SfinaeTest
{    
   SfinaeTest() = default;

   SfinaeTest(const SfinaeTest&) = default;

   template<typename TT, typename enable_if< !is_const<TT>::value, int>::type =
0>
   SfinaeTest(const SfinaeTest<TT>& other)
   { }
};

int main ()
{
    SfinaeTest<int>     p;
    SfinaeTest<const int> c;

    SfinaeTest<int> b_c( c);   // expected error. Extra gcc-error: see L:13
}

GCC prints two errors, one is the substitution failure error.

Clang only prints one, for the invalid constructor call for b_c. Clang has a
special case for enable_if constraints, where it prints the boolean condition:

<source>:14:4: note: candidate template ignored: requirement '!is_const<const
int>::value' was not satisfied [with TT = const int]

If we rename the enable_if template, Clang still doesn't show an error, but is
closer to GCC's wording:

template<bool, typename T> struct require { };
template<typename T> struct require<true, T> { using type = T; };
template<typename T> struct is_const { static constexpr bool value = false; };
template<typename T> struct is_const<const T> { static constexpr bool value =
true; };

template<typename T>
struct SfinaeTest
{    
   SfinaeTest() = default;

   SfinaeTest(const SfinaeTest&) = default;

   template<typename TT, typename require< !is_const<TT>::value, int>::type =
0>
   SfinaeTest(const SfinaeTest<TT>& other)
   { }
};

int main ()
{
    SfinaeTest<int>     p;
    SfinaeTest<const int> c;

    SfinaeTest<int> b_c( c);   // expected error. Extra gcc-error: see L:15
}

Now clang's note for the template constructor says:

<source>:14:4: note: candidate template ignored: substitution failure [with TT
= const int]: no type named 'type' in 'require<false, int>'


So the only real difference is that gcc prints the cause of the substitution
failure as an error.


More information about the Gcc-bugs mailing list