【问题标题】:Passing std::integer_sequence as template parameter to a meta function将 std::integer_sequence 作为模板参数传递给元函数
【发布时间】:2015-08-08 12:24:15
【问题描述】:

如何将std::integer_sequence 作为模板参数传递给元函数(即不是函数模板)?

给定例如以下用例(但不限于此):

我想使用整数序列从参数包中删除最后一个 N 类型。我以为我可以使用this SO question 中的selector,但我无法将整数序列传递给这个元函数。

#include <tuple>
#include <utility>

template <typename T, std::size_t... Is>
struct selector
{
    using type = std::tuple<typename std::tuple_element<Is, T>::type...>;
};

template <std::size_t N, typename... Ts>
struct remove_last_n
{
    using Indices = std::make_index_sequence<sizeof...(Ts)-N>;  
    using type = typename selector<std::tuple<Ts...>, Indices>::type; // fails
};

int main()
{
    using X = remove_last_n<2, int, char, bool, int>::type;
    static_assert(std::is_same<X, std::tuple<int, char>>::value, "types do not match");
}

编译器错误

main.cpp:15:55: error: template argument for non-type template parameter must be an expression

using type = typename selector<std::tuple<Ts...>, Indices>::type; // fails

                                                  ^~~~~~~

main.cpp:5:38: note: template parameter is declared here

template <typename T, std::size_t... Is>

live on coliru

如何传递整数序列?

【问题讨论】:

    标签: c++ templates c++14


    【解决方案1】:

    您需要(部分)专门化 selector 以便从 std::index_sequence 推导出索引:

    #include <tuple>
    #include <utility>
    #include <type_traits>
    
    template <typename T, typename U>
    struct selector;
    
    template <typename T, std::size_t... Is>
    struct selector<T, std::index_sequence<Is...>>
    {
        using type = std::tuple<typename std::tuple_element<Is, T>::type...>;
    };
    
    template <std::size_t N, typename... Ts>
    struct remove_last_n
    {
        using Indices = std::make_index_sequence<sizeof...(Ts)-N>;  
        using type = typename selector<std::tuple<Ts...>, Indices>::type;
    };
    
    int main()
    {
        using X = remove_last_n<2, int, char, bool, int>::type;
        static_assert(std::is_same<X, std::tuple<int, char>>::value, "types do not match");
    }
    

    DEMO

    【讨论】:

      【解决方案2】:

      对于这么简单的用例,您也可以将元函数编写为函数模板。

      template<class...> class wrapper{};
      
      template <typename T, std::size_t... Is>
      std::tuple<typename std::tuple_element<Is, T>::type...>
          selector_impl(wrapper<T, std::index_sequence<Is...>>);    
      
      template <std::size_t N, typename... Ts>
      struct remove_last_n
      {
          using Indices = std::make_index_sequence<sizeof...(Ts)-N>;  
          using type = decltype(selector_impl(wrapper<std::tuple<Ts...>, Indices>()));
      };
      

      顺便说一下,selectortuple_element 实现通常效率很低,因为所需的递归模板实例化的数量是二次方的。 This answer 展示了一种方法,使所需的模板实例化数量与列表中的类型数量成线性关系。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-25
        • 2020-12-17
        相关资源
        最近更新 更多