在类型特征中获取 std::reference_wrapper 内的原始类型

Get raw type inside std::reference_wrapper in type trait

问题

我有一个用于数学运算的自定义向量类型。我可以直接给它一个类型

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

或 reference_wrapper

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

两者都有效。

但是,我想限制 MyVector class 只接受算术类型。考虑将 static_assert 放入 class 中,如下所示:

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

当然这对 reference_wrapper<int> 是失败的。

问题

如何“展开”std::reference_wrapper 以获得基础类型并将其用于类型特征?

你可以试试:

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;

并使用static_assert(std::is_arythmetic_type_v<unwrap_ref_type<T>>);

您可以使用 std::conditional_tstd::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{};

然后

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

注意:std::conditional 中提供的类型是“已评估”的,因此您不能

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

所以我们将评估延迟到外部(两种类型都应该有 ::type,而 C++20 std::type_identity 有一个:))