【问题标题】:Get raw type inside std::reference_wrapper in type trait在类型特征中获取 std::reference_wrapper 中的原始类型
【发布时间】:2020-12-10 11:16:50
【问题描述】:

问题

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

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 类限制为仅采用算术类型。考虑在类中放置一个 static_assert,如下所示:

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

但对于reference_wrapper&lt;int&gt;,这当然会失败。

问题

我如何“解包”一个 std::reference_wrapper 以获取底层类型并在类型特征中使用它?

【问题讨论】:

    标签: c++ reference c++14 typetraits


    【解决方案1】:

    你可以试试:

    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&lt;unwrap_ref_type&lt;T&gt;&gt;);

    【讨论】:

    • 效果很好,谢谢!不过请注意:我用std::reference_wrapper替换了你的std::reference_type
    【解决方案2】:

    您可以使用std::conditional_tstd::reference_wrapper&lt;T&gt;::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 有一个 :))

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-05
      • 2021-01-04
      • 1970-01-01
      • 2020-11-28
      • 2021-09-14
      • 1970-01-01
      • 1970-01-01
      • 2016-07-31
      相关资源
      最近更新 更多