Jonathan
Jonathan

Reputation: 752

How can I use std::decay when partially specializing a type trait?

I made these type traits to determine if the type is a dynamic container, but recently ran into confusion when a reference to a vector didn't return true.

template<typename T>
struct is_dynamic_container
{
    static const bool value = false;
};

template<typename T , typename Alloc>
struct is_dynamic_container<std::vector<T , Alloc>>
{
    static const bool value = true;
};

I think I need to use std::decay, but I'm having trouble figuring out if it can be done like this rather than at the call site.

template<typename T , typename Alloc>
struct is_dynamic_container<std::decay<std::vector<T , Alloc>>::type>
{
    static const bool value = true;
};

^^This doesn't work.

I just want to be able to write is_dynamic_container<std::vector<int>&> and not is_dynamic_container<std::decay<std::vector<int>&>::type>. Is that possible?

Upvotes: 3

Views: 788

Answers (2)

T.C.
T.C.

Reputation: 137395

template<class T>
using is_dynamic_container_with_decay = is_dynamic_container<std::decay_t<T>>;

Upvotes: 5

Daniel Frey
Daniel Frey

Reputation: 56921

You could try this:

template<typename T,typename=void>
struct is_dynamic_container
{
    static const bool value = false;
};

template<typename T>
struct is_dynamic_container<T,
  typename std::enable_if<
    !std::is_same<T,typename std::decay<T>::type>::value,
  >::type
>
    : is_dynamic_container<typename std::decay<T>::type>
{};

If you don't mind an intermediate step, there is a simpler and more conservative solution. Rename is_dynamic_container to is_dynamic_container_impl and then

template<typename T>
using is_dynamic_container =
  is_dynamic_container_impl<typename std::decay<T>::type>;

Choose whatever is appropriate in your case.

Upvotes: 3

Related Questions