在类型特征中获取 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_t
和 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{};
然后
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");
注意: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
有一个:))
问题
我有一个用于数学运算的自定义向量类型。我可以直接给它一个类型
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_t
和 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{};
然后
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");
注意: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
有一个:))