2015-08-08 38 views
8

Bir std::integer_sequence şablon parametresi olarak bir meta işlevine nasıl (örn. Bir işlev şablonu değil) geçirebilirim? Verilen örnek: örn. Aşağıdaki kullanım durumu (ancak bununla sınırlı değildir):std :: integer_sequence işlevinin bir meta işlevine geçirilmesi

Bir parametre paketinden son N türlerini kaldırmak için bir tamsayı dizisi kullanmak istiyorum. selector'u this SO question'dan kullanabileceğimi düşündüm, ancak tamsayı dizisini bu meta işlevine iletemedim.

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

derleyici hatası

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

nasıl tamsayı dizisi geçerdi?

cevap

10

Buna gerek (kısmen) endeksleri std::index_sequence çıkarılabilir böylece selector uzmanlaşmak:

#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"); 
} 
bir kullanım durumunda bu basit için

DEMO

+0

İnanılmaz hızlı! –

1

, bunun yerine bir işlev şablonu olarak üst-işlevin yazabilir . Gerekli özyinelemeli şablon örneklemesi sayısı kuadratik çünkü

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

arada, selector ait tuple_element uygulanması, genellikle oldukça verimsiz. This answer, listedeki tür sayısında doğrusal olması gereken şablon örnekleme sayısını belirlemenin bir yolunu gösterir.

İlgili konular