Patrick Wright
Patrick Wright

Reputation: 1663

Specialize template class depending on trait

I am attempting to figure out how to special a template class based upon the result of a template. For example, suppose I have the following basic template class:

enum class BasicType
{
    UNKNOWN,
    PRIMITIVE,
    OBJECT
};

template <typename T>
struct traits
{
    static constexpr BasicType type = BasicType::UNKNOWN;
};

I want to be able to create a specialization of traits, for example, for any types where std::is_integral_v is true. And then another specialization where another traits is true.

I tried something like this

template <typename T>
struct traits<std::enable_if_t<std::is_integral_v<T>, T>>
{
    static constexpr BasicType type = BasicType::PRIMITIVE;
};

But this doesn't work.

Upvotes: 3

Views: 271

Answers (1)

Timo
Timo

Reputation: 9825

You're close, but the problem with using enable_if like this is that it prevents type deduction. Basically, the compiler is unable to ever match your template specialization. What you can do, though, is to move the enable_if part to a second template parameter next to your T so it can be deduced:

template <typename T, typename = void>
struct traits
{
    static constexpr BasicType type = BasicType::UNKNOWN;
};

template <typename T>
struct traits<T, std::enable_if_t<std::is_integral_v<T>>>
{
    static constexpr BasicType type = BasicType::PRIMITIVE;
};

This works because T is no longer hidden behind another template. The compiler is still unable to deduce T from std::enable_if_t<std::is_integral_v<T>>, but because you also specified T direclty here: struct traits<T, ...>, the compiler can deduce T this way, which is enough to match your specialization.

example

Upvotes: 7

Related Questions