将std :: integer_sequence作为模板参数传递给元函数

时间:2015-08-08 12:24:15

标签: c++ templates c++14

如何将<div class="parent"> <div class="static_child"> </div> <div class="static_child"> </div> </div> .parent { border: 1px solid black; display: flex; flex-direction: column; } .static_child { border: 1px solid red; width: 600px; height: 200px; } 作为模板参数传递给元函数(即不是函数模板)?

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

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

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");
}

live on coliru

我如何传递整数序列?

2 个答案:

答案 0 :(得分:12)

您需要(部分)专门化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

答案 1 :(得分:1)

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

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>()));
};

顺便说一下,tuple_element selector的实现效率通常非常低,因为所需的递归模板实例化的数量是二次的。 This answer显示了一种方法,可以使列表中类型数量的模板实例化数量呈线性。