2015-08-08 159 views
8

如何將std::integer_sequence作爲模板參數傳遞給元函數(即不是函數模板)?將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

我將如何傳遞的整數序列?

回答

10

你需要(部分)專門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

+0

難以置信的快! –

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顯示了使列表中的類型數量所需的線性模板實例化數量的一種方法。

相關問題