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

            Bug ID: 87464
           Summary: Gcc reports hard error instead of SFINAE out the
                    related method
           Product: gcc
           Version: 7.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: alexejfink at gmx dot net
  Target Milestone: ---

Created attachment 44765
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44765&action=edit
test code

The following code works with clang (7.x, 8.x) & VC (2015).

Trouble: GCC reports a hard error instead of SFINAE-drop the methods:
1. "tst.cpp:27:149: error: no type named ‘type’ in ‘struct
std::enable_if<false, int>’";
2. "tst.cpp:36:4: error: no type named ‘type’ in ‘struct std::enable_if<false,
SfinaeTest<int>&>’"

The clang and VC compilers do compile this places (besides the expected errors
in main())




//== sfinae_gcc_error.cpp =======================

#include <type_traits>

template<typename T>
class SfinaeTest
{
public:

   SfinaeTest()
    : dummy(nullptr)
   { }

   SfinaeTest(const SfinaeTest& other)
    : dummy(other.dummy)
   { }

   SfinaeTest& operator =(const SfinaeTest& ot)
   {
      dummy= ot.dummy;
      return *this;
   }

public: // forbid non-const = const assignements

   // gcc reports an error: "tst.cpp:27:149: error: no type named ‘type’ in
‘struct std::enable_if<false, int>’";
   // Clang & VC do compile this constructor
   template<typename TT, typename std::enable_if< std::is_same<T, const
TT>::value, int>::type = 0>
   SfinaeTest(const SfinaeTest<TT>& other)
    : dummy(other.dummy)
   { }

   // gcc reports an error "tst.cpp:36:4: error: no type named ‘type’ in
‘struct std::enable_if<false, SfinaeTest<int>&>’"
   // clang & VC do compile this method
   template<typename TT>
   typename std::enable_if< std::is_same<T, const TT>::value,
SfinaeTest&>::type
   operator =(const SfinaeTest<TT>& ot)
   {
      dummy= ot.dummy;

      return *this;
   }

public:

   T* dummy;
};

int main ()
{
    typedef SfinaeTest<int> Ptr;
    typedef SfinaeTest<const int> ConstPtr;

    Ptr      p;
    ConstPtr c;

    ConstPtr a_p( p);   // good: non-const* -> const*
    ConstPtr a_c( c);   // good: const* -> const*
    Ptr      b_c( c);   // expected error: const* -> non-const*; Extra
gcc-error: see L:25

    ConstPtr c_p;
    ConstPtr c_c;
    Ptr      d_p;
    Ptr      d_c;
    c_p = p;            // good: non-const* -> const*
    c_c = c;            // good: const* -> const*
    d_p = p;            // good: non-const* -> non-const*
    d_c = c;            // expected error: const* -> non-const*; Extra
gcc-error, see L:32

    return 0;
}

//== GCC =======================

/tmp/sfinae_test$ /usr/bin/c++ --version 
c++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

/tmp/sfinae_test$ /usr/bin/c++ -c sfinae_gcc_error.cpp 
sfinae_gcc_error.cpp: In function ‘int main()’:
sfinae_gcc_error.cpp:58:20: error: no matching function for call to
‘SfinaeTest<int>::SfinaeTest(ConstPtr&)’
     Ptr      b_c( c);   // expected error: const* -> non-const*; Extra
gcc-error: see L:25
                    ^
sfinae_gcc_error.cpp:28:4: note: candidate: template<class TT, typename
std::enable_if<std::is_same<int, const TT>::value, int>::type <anonymous> >
SfinaeTest<T>::SfinaeTest(const SfinaeTest<TT>&)
    SfinaeTest(const SfinaeTest<TT>& other)
    ^~~~~~~~~~
sfinae_gcc_error.cpp:28:4: note:   template argument deduction/substitution
failed:
sfinae_gcc_error.cpp:27:98: error: no type named ‘type’ in ‘struct
std::enable_if<false, int>’
    template<typename TT, typename std::enable_if< std::is_same<T, const
TT>::value, int>::type = 0>
                                                                               
                  ^
sfinae_gcc_error.cpp:27:98: note: invalid template non-type parameter
sfinae_gcc_error.cpp:13:4: note: candidate: SfinaeTest<T>::SfinaeTest(const
SfinaeTest<T>&) [with T = int]
    SfinaeTest(const SfinaeTest& other)
    ^~~~~~~~~~
sfinae_gcc_error.cpp:13:4: note:   no known conversion for argument 1 from
‘ConstPtr {aka SfinaeTest<const int>}’ to ‘const SfinaeTest<int>&’
sfinae_gcc_error.cpp:9:4: note: candidate: SfinaeTest<T>::SfinaeTest() [with T
= int]
    SfinaeTest()
    ^~~~~~~~~~
sfinae_gcc_error.cpp:9:4: note:   candidate expects 0 arguments, 1 provided
sfinae_gcc_error.cpp:67:11: error: no match for ‘operator=’ (operand types are
‘Ptr {aka SfinaeTest<int>}’ and ‘ConstPtr {aka SfinaeTest<const int>}’)
     d_c = c;            // expected error: const* -> non-const*; Extra
gcc-error, see L:32
           ^
sfinae_gcc_error.cpp:17:16: note: candidate: SfinaeTest<T>&
SfinaeTest<T>::operator=(const SfinaeTest<T>&) [with T = int]
    SfinaeTest& operator =(const SfinaeTest& ot)
                ^~~~~~~~
sfinae_gcc_error.cpp:17:16: note:   no known conversion for argument 1 from
‘ConstPtr {aka SfinaeTest<const int>}’ to ‘const SfinaeTest<int>&’
sfinae_gcc_error.cpp:36:4: note: candidate: template<class TT> typename
std::enable_if<std::is_same<T, const TT>::value, SfinaeTest<T>&>::type
SfinaeTest<T>::operator=(const SfinaeTest<TT>&) [with TT = TT; T = int]
    operator =(const SfinaeTest<TT>& ot)
    ^~~~~~~~
sfinae_gcc_error.cpp:36:4: note:   template argument deduction/substitution
failed:
sfinae_gcc_error.cpp: In substitution of ‘template<class TT> typename
std::enable_if<std::is_same<int, const TT>::value, SfinaeTest<int>&>::type
SfinaeTest<int>::operator=<TT>(const SfinaeTest<TT>&) [with TT = const int]’:
sfinae_gcc_error.cpp:67:11:   required from here
sfinae_gcc_error.cpp:36:4: error: no type named ‘type’ in ‘struct
std::enable_if<false, SfinaeTest<int>&>’


//== CLANG =======================


/tmp/sfinae_test$ /usr/bin/clang++ --version
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

/tmp/sfinae_test$ /usr/bin/clang++ -c sfinae_gcc_error.cpp 
sfinae_gcc_error.cpp:58:14: error: no matching constructor for initialization
of 'Ptr' (aka 'SfinaeTest<int>')
    Ptr      b_c( c);   // expected error: const* -> non-const*; Extra
gcc-error: see L:25
             ^    ~
sfinae_gcc_error.cpp:13:4: note: candidate constructor not viable: no known
conversion from 'SfinaeTest<const int>' to 'const SfinaeTest<int>' for
      1st argument
   SfinaeTest(const SfinaeTest& other)
   ^
sfinae_gcc_error.cpp:28:4: note: candidate template ignored: requirement
'std::is_same<int, const const int>::value' was not satisfied
      [with TT = const int]
   SfinaeTest(const SfinaeTest<TT>& other)
   ^
sfinae_gcc_error.cpp:9:4: note: candidate constructor not viable: requires 0
arguments, but 1 was provided
   SfinaeTest()
   ^
sfinae_gcc_error.cpp:67:9: error: no viable overloaded '='
    d_c = c;            // expected error: const* -> non-const*; Extra
gcc-error, see L:32
    ~~~ ^ ~
sfinae_gcc_error.cpp:17:16: note: candidate function not viable: no known
conversion from 'SfinaeTest<const int>' to 'const SfinaeTest<int>' for
      1st argument
   SfinaeTest& operator =(const SfinaeTest& ot)
               ^
sfinae_gcc_error.cpp:36:4: note: candidate template ignored: requirement
'std::is_same<int, const const int>::value' was not satisfied
      [with TT = const int]
   operator =(const SfinaeTest<TT>& ot)
   ^
2 errors generated.
/tmp/sfinae_test$ 


//== END =======================

Reply via email to