HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

A trait class to detect whether a template is specialized for a given type

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
templatewhetherspecializedtypetraitforclassgivendetect

Problem

Today's question will just be about a small utility that I needed at some point for one of my projects: a template to detect whether a template is specialized for a given type. The utility uses std::void_t from C++17, but this alias template is simle enough to be implemented in you favourite C++ revision, whichever it is:

template
struct voider
{
    using type = void;
};

template
using void_t = typename voider::type;


Here is the template utility I wrote to detect whether a template has a specialization for a given type, for SFINAE purpose:

template class,
    typename,
    typename=void
>
struct is_specialized:
    std::false_type
{};

template class Template,
    typename T
>
struct is_specialized{})>>:
    std::true_type
{};


And here is a small example of how it can be used:

template
struct foo;

template<>
struct foo {};

template<>
struct foo {};

int main()
{
    // Should print 1 1 0
    std::cout ::value ::value ::value;
}


Is there any way I could improve this specialization trait? Any kind of review is welcome :)

Solution

I think there's an issue with wording here. What you're testing is if a given instantiation of a class template is default constructible. You're not testing if it's "specialized". You cannot check for that. How would you differentiate between:

template  struct foo { };
template <> struct foo { };

// is foo the primary or the specialization?


Back to your example - just because you cannot construct an object of a particular instantiation (e.g. foo) doesn't mean that you can't name the type. You can do that just fine. That lets you simplify your trait down to:

template 
struct is_specialized : std::false_type
{};

template
struct is_specialized>
    : std::true_type
{};


Which you would use as is_specialized::value (true) or is_specialized>::value (false).

But really, since we're just testing for constructibility, we should just use what's in the standard:

template 
using is_specialized = std::is_default_constructible;

Code Snippets

template <typename T> struct foo { };
template <> struct foo<int> { };

// is foo<X> the primary or the specialization?
template <typename, typename=void>
struct is_specialized : std::false_type
{};

template<typename T>
struct is_specialized<T, void_t<decltype(T{})>>
    : std::true_type
{};
template <typename T>
using is_specialized = std::is_default_constructible<T>;

Context

StackExchange Code Review Q#98214, answer score: 6

Revisions (0)

No revisions yet.