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 =======================