Hi, More strange: by adding an unused static method, the behavior of the previous templates change.
$ cat toto6.cpp #include <iostream> struct X { template <class T, class U = void> struct check_is_map { static constexpr bool value = false; }; template <class T> struct check_is_map<T, typename T::is_map> { static constexpr bool value = true; }; template <class T> struct check_is_map2 { static constexpr bool value = check_is_map<T>::value; }; static void func(); }; template <class T, class U = void> struct check_is_map { static constexpr bool value = false; }; template <class T> struct check_is_map<T, typename T::is_map> { static constexpr bool value = true; }; struct Config { using is_map=void; }; struct ConfigBis { private: template <typename T1, typename U1> friend struct check_is_map; friend struct X; using is_map=void; }; #ifdef FOO void X::func() { std::cerr << "* Through method" << std::endl; std::cerr << "X::VALUE (public): " << X::check_is_map<Config>::value << std::endl; std::cerr << "X::VALUE (private+friend): " << X::check_is_map<ConfigBis>::value << std::endl; std::cerr << "** By proxy template" << std::endl; std::cerr << "X::Proxy::VALUE (public): " << X::check_is_map2<Config>::value << std::endl; std::cerr << "X::Proxy::VALUE (private+friend): " << X::check_is_map2<ConfigBis>::value << std::endl; } #endif int main() { std::cerr << "* From main" << std::endl; std::cerr << "VALUE (public): " << check_is_map<Config>::value << std::endl; std::cerr << "VALUE (private+friend): " << check_is_map<ConfigBis>::value << std::endl; std::cerr << "X::VALUE (public): " << X::check_is_map<Config>::value << std::endl; std::cerr << "X::VALUE (private+friend): " << X::check_is_map<ConfigBis>::value << std::endl; std::cerr << "** By proxy template" << std::endl; std::cerr << "X::Proxy::VALUE (public): " << X::check_is_map2<Config>::value << std::endl; std::cerr << "X::Proxy::VALUE (private+friend): " << X::check_is_map2<ConfigBis>::value << std::endl; } $ g++ -std=gnu++17 -Wall -Wextra toto6.cpp $ ./a.out * From main VALUE (public): 1 VALUE (private+friend): 0 X::VALUE (public): 1 X::VALUE (private+friend): 0 ** By proxy template X::Proxy::VALUE (public): 1 X::Proxy::VALUE (private+friend): 0 $ g++ -std=gnu++17 -Wall -Wextra toto6.cpp -DFOO $ ./a.out * From main VALUE (public): 1 VALUE (private+friend): 0 X::VALUE (public): 1 X::VALUE (private+friend): 1 ** By proxy template X::Proxy::VALUE (public): 1 X::Proxy::VALUE (private+friend): 1 Regards, Vincent