Search code examples
c++templatessfinaetype-traitscompile-time-constant

Why does this of sfinae not work?


#include <type_traits>

using namespace std;

struct A
{
    using key_type = int;
};

template<typename T, typename = void>
struct has_key_type : false_type
{};

template<typename T>
struct has_key_type<T, decltype(typeid(typename T::key_type), void())>: true_type
{};

int main()
{
    cout << has_key_type<A>::value << endl;
    cout << has_key_type<int>::value << endl;
}

The output is:

1
0

Which is as expected. However, if I change from

decltype(typeid(typename T::key_type), void())

to

decltype(typeid(typename T::key_type), int())

as follows:

template<typename T>
struct has_key_type<T, decltype(typeid(typename T::key_type), int())>: true_type
{};

The output is:

0
0

Why does the second version not work?


Solution

  • You did not give the second template argument, so it will use the default template argument, which is void. In your second version, the type of decltype(typeid(typename T::key_type), int()) is int, so has_key_type<A>, which is equivalently has_key_type<A, void>, will certainly not match this partial specialization.

    BTW, since C++17, you can use std::void_t to simplify decltype(typeid(typename T::key_type), void()) to std::void_t<typename T::key_type>.