xmllmx
xmllmx

Reputation: 42379

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?

Upvotes: 3

Views: 73

Answers (1)

xskxzr
xskxzr

Reputation: 13040

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

Upvotes: 4

Related Questions