【问题标题】:How to simply the parameters when using a global std::array reference as a template parameter?使用全局 std::array 引用作为模板参数时如何简化参数?
【发布时间】:2019-12-21 11:32:43
【问题描述】:

这适用于 C++17:

template <std::size_t N, const std::array<int, N> & ARRAY> class Foo {};

constexpr std::array<int, 3> A{1, 2, 3};

void bar()
{
    Foo<3, A> foo_a;
}

那么有没有办法避免在Foo的模板参数中写入N呢?因为我们可以很容易地从ARRAY.size() 知道它。我试过了,但失败了:

template <template <size_t N> const std::array<int, N> & ARRAY> Foo {}; // Error.

【问题讨论】:

    标签: c++ templates c++17 constexpr template-argument-deduction


    【解决方案1】:

    您无需指定引用的确切类型。您可以使用占位符:

    #include<array>
    
    template <auto& ARRAY> class Foo {
        static constexpr auto N = ARRAY.size();
    };
    
    constexpr std::array<int, 3> A{1, 2, 3};
    
    void bar()
    {
        Foo<A> foo_a;
    }
    

    如果你想在模板参数不是对std::array&lt;int, ...&gt;的引用时得到一个错误,你可以写一个类型特征告诉你类型是否是std::array的实例化并检查value_type

    #include<array>
    #include<type_traits>
    
    template<typename>
    struct is_std_array : std::false_type {};
    
    template<typename T, std::size_t N>
    struct is_std_array<std::array<T, N>> : std::true_type {};
    
    template<typename T>
    inline constexpr auto is_std_array_v = is_std_array<T>::value;
    
    // std::remove_cvref_t will be part of C++20
    template<typename T>
    using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
    
    template<auto& ARRAY>
    class Foo {
        using ARRAY_type = remove_cvref_t<decltype(ARRAY)>;
    
        static_assert(is_std_array_v<ARRAY_type>,
            "Foo requires reference to std::array of int as template argument!");
        static_assert(std::is_same_v<typename ARRAY_type::value_type, int>,
            "Foo requires reference to std::array of int as template argument!");
    
        constexpr static auto N = ARRAY.size();
    };
    
    constexpr std::array<int, 3> A{1, 2, 3};
    constexpr std::array<long, 3> B{1, 2, 3};
    constexpr int C = 5;
    
    void bar()
    {
        Foo<A> foo_a;
        // Foo<B> foo_b; // Will give static_assert error message
        // Foo<C> foo_c; // Will give static_assert error message
    }
    

    在 C++20 中会有一些概念,这将允许您编写一个概念来测试我现在使用 static_asserts 测试的属性,您将能够使用该概念来代替 auto在模板参数中。

    【讨论】:

      【解决方案2】:

      通过偏特化的可能解决方案

      template <auto const &>
      class Foo;
      
      template <std::size_t N, std::array<int, N> const & ARRAY>
      class Foo<ARRAY>
       { };
      

      所以你可以写

      constexpr std::array<int, 3> A{1, 2, 3};
      
      int main ()
       {
          Foo<A> foo_a;
       }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-01-27
        • 2019-06-24
        • 1970-01-01
        • 1970-01-01
        • 2013-05-25
        • 2017-10-10
        • 1970-01-01
        相关资源
        最近更新 更多