2015-08-08 23 views
8

Làm cách nào để chuyển một tham số mẫu vào một hàm meta (tức là không phải mẫu chức năng)?Chuyển std :: integer_sequence làm tham số mẫu thành hàm meta

Ví dụ: trường hợp sử dụng sau đây (nhưng không giới hạn trong trường hợp này):

Tôi muốn sử dụng trình tự số nguyên để xóa các loại N cuối cùng khỏi gói tham số. Tôi nghĩ rằng tôi có thể sử dụng selector từ this SO question, nhưng tôi không vượt qua chuỗi số nguyên để chức năng meta này.

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

biên dịch lỗi

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

Làm thế nào tôi có thể vượt qua các dãy số nguyên?

Trả lời

10

Bạn cần (một phần) chuyên selector để chỉ số này được rút ra từ 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

nhanh không thể tin được! –

1

Đối với một trường hợp sử dụng đơn giản này, bạn cũng có thể viết metafunction như một hàm template thay vì .

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

Ngẫu nhiên, việc thực hiện tuple_element của selector nói chung là khá hiệu quả, vì số lượng mẫu instantiations đệ quy cần là bậc hai. This answer cho thấy một cách để làm cho số lượng các mẫu tức thời được yêu cầu tuyến tính trong số loại trong danh sách.

Các vấn đề liên quan