Marc Pawlowsky <marcpawl@gmail.com> Thu, Nov 28, 8:25 PM (23 hours ago) to gcc-bugzilla-account-request https://godbolt.org/z/SFZmZJ In clang you get no member names 'hello' in 'Bad' which is the expected result. In all GCC versions using --std=c++17 from 5.2 onwards the code compiles. #include <type_traits> #include <cstdio> struct Foo { virtual void hello(int) = 0; }; struct Bar : public Foo { void hello(int) override {}; }; struct Bad { }; template <typename T> struct is_Foo { using hello_fn_t = void (T::*)(int); constexpr static void (T::*hello)(int) = &T::hello; static constexpr bool value=true; }; template <typename T> auto say(T& t) -> std::enable_if_t<is_Foo<T>::value, void>{ //U u; // Line 22 //t.hello(4); // Line 23 puts("hello\n"); } int main() { //Bar b;; //Foo& f = b; //say(b); //say(f); Bad bad; say(bad); } If you change say to template <typename T, typename U=is_Foo<T>> void say(T& t) { U u; // Line 22 //t.hello(4); // Line 23 } you get the same errors in clang, but no errors in gcc. == on a related not I sent to clang bug report where if value is not static the code will compile.
(In reply to Marc Pawlowsky from comment #0) > on a related not I sent to clang bug report where if value is not static the > code will compile. https://bugs.llvm.org/show_bug.cgi?id=44175 (I think that's not a bug).
For the case reported here, Clang and EDG do reject it, but I'm not yet convinced GCC is wrong to accept it. The implicit instantiation of is_Foo<Bad> causes: "the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends;" and: "in particular, the initialization (and any associated side effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist." Nothing requires the instantiation of is_Foo<Bad>::hello.
Related to http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1396
(In reply to Jonathan Wakely from comment #2) > For the case reported here, Clang and EDG do reject it, but I'm not yet > convinced GCC is wrong to accept it. > > The implicit instantiation of is_Foo<Bad> causes: > > "the implicit instantiation of the declarations, but not of the definitions, > of the non-deleted class member functions, member classes, scoped member > enumerations, static data members, member templates, and friends;" > > and: > > "in particular, the initialization (and any associated side effects) of a > static data member does not occur unless the static data member is itself > used in a way that requires the definition of the static data member to > exist." > > Nothing requires the instantiation of is_Foo<Bad>::hello. FYI, Forcing the use of hello does cause a compile time error. template <typename T> struct is_Foo { using hello_fn_t = void (T::*)(int); constexpr static void (T::*hello)(int) = &T::hello; static constexpr bool value=(!!hello); }; source>:16:46: error: 'hello' is not a member of 'Bad' 16 | constexpr static void (T::*hello)(int) = &T::hello;