mtosch
mtosch

Reputation: 461

Get raw type inside std::reference_wrapper in type trait

Problem

I have a custom vector type for math operations. I can give it a type directly

MyVector<2, int>vec{4,5};

or a reference_wrapper

int num1 = 4;
int num2 = 5;
MyVector<2, std::reference_wrapper<int>> vec2{std::ref(num1), std::ref(num2)};

which both works.

However, i'd like to restrict the MyVector class to only take arithmetic types. Thought about putting a static_assert inside the class like this:

static_assert(std::is_arithmetic_v<T>, "Vector type T must be an arithmetic");

but of course this fails for reference_wrapper<int>.

Question

How can i "unwrap" an std::reference_wrapper to get the underlying type and use it in a type trait?

Upvotes: 1

Views: 430

Answers (2)

Jarod42
Jarod42

Reputation: 218238

You might use std::conditional_t and std::reference_wrapper<T>::type:

// Helper
template <typename T> struct is_reference_wrapper : std::false_type{};
template <typename T> struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type{};

And then

static_assert(std::is_arithmetic_v<
                  typename std::conditional_t<
                      is_reference_wrapper<T>::value,
                      T,
                      std::type_identity<T>
                  >::type // Notice the extra type (in addition to _t)
              >,
              "Vector type T must be an arithmetic");

Demo

Note: Types provided in std::conditional are "evaluated", so you can't do

std::conditional_t<is_reference_wrapper<T>::value,
                   typename T::type, // Hard error for types without `type` typename
                   T
                  >

so we delay that evaluation outside (both types should have ::type, and C++20 std::type_identity has one :) )

Upvotes: 0

PiotrNycz
PiotrNycz

Reputation: 24420

You might try:

template <typename T>
struct unwrap_ref 
{
    using type = T;
};
template <typename T>
struct unwrap_ref<std::reference_wrapper<T>> 
{
    using type = T;
};

template <typename T>
using unwrap_ref_type = typename unwrap_ref<T>::type;

And use static_assert(std::is_arythmetic_type_v<unwrap_ref_type<T>>);

Upvotes: 3

Related Questions