2016-10-12 17 views
8

Tôi có vấn đề sau đây:Mở rộng một loại N lần trong mẫu tham số

template< std::size_t N > 
class A 
{ 
    std::function< std::size_t(/*std::size_t,....,std::size_t <- N-times*/) > foo; 
}; 

Như bạn thấy ở trên, tôi cố gắng để khai báo một std::function<...> foo như một thành viên của một lớp A. Ở đây, tôi muốn foo để có kiểu trả về std::size_t (không có vấn đề gì) và như đầu vào, tôi sẽ vượt qua N-lần loại std::size_t nhưng tôi không biết làm thế nào. Có khả năng nào không?

Rất cám ơn trước.

Trả lời

12

Bạn có thể sử dụng std::index_sequence:

template<typename> 
struct AHelper; 

template<std::size_t... S> 
struct AHelper<std::index_sequence<S...>> { 
    std::function<std::size_t(decltype(S)...)> foo; 
}; 

template<std::size_t N> 
struct A : AHelper<std::make_index_sequence<N>> {}; 

Live example at coliru

Nếu bạn thích, bạn cũng có thể xác định những gì loại nó mở rộng:

template<typename, typename> 
struct AHelper; 

template<typename T, std::size_t... S> 
struct AHelper<T, std::index_sequence<S...>> { 
    template<std::size_t> 
    using type = T; 

    std::function<std::size_t(type<S>...)> foo; 
}; 

template<typename T, std::size_t N> 
struct A : AHelper<T, std::make_index_sequence<N>> {}; 
+1

giải pháp tuyệt vời. Sạch hơn tôi. – bolov

+0

Đối với những người đang gặp khó khăn để tìm định nghĩa: 'std :: index_sequence' là một bí danh trợ giúp được định nghĩa trong '' như một "[helper alias template \ [of' std :: integer_sequence' \] cho trường hợp chung 'T' là 'std :: size_t'] (http://en.cppreference.com/w/cpp/utility/integer_sequence#Helper_templates)." –

+0

Và sau đó cho một cái gì đó tổng quát hơn một chút bạn có thể có một 'mẫu bằng cách sử dụng make_type_wrapper = T;' Bằng cách đó nếu bạn muốn một cái gì đó khác hơn 'size_t' như chữ ký bạn có thể sử dụng wrapper thay thế – SirGuy

1

Ok điều này thật thú vị. Đây là giải pháp của tôi:

namespace details { 
template <size_t N, class F = size_t()> 
struct Function_type_helper {}; 

template <size_t N, class... Args> 
struct Function_type_helper<N, size_t(Args...)> { 
    using Type = typename Function_type_helper<N - 1, size_t(Args..., size_t)>::Type; 
}; 

template <class... Args> 
struct Function_type_helper<0, size_t(Args...)> { 
    using Type = size_t(Args...); 
}; 

template <size_t N, class F = size_t()> 
using Function_type_helper_t = typename Function_type_helper<N, F>::Type; 

static_assert(std::is_same_v<Function_type_helper_t<3>, size_t(size_t, size_t, size_t)>); 
} // ns details 

template<size_t N> 
struct A 
{ 
    std::function<details::Function_type_helper_t<N>> foo; 
}; 

này hoạt động bằng cách đệ quy để tạo Loại size_t(size_t, size_t, ..., size_t)

Ví dụ:

H<3>::Type == H<3, size_t()>::Type == 
       H<2, size_t(size_t)>::Type == 
       H<1, size_t(size_t, size_t)>::Type == 
       H<0, size_t(size_t, size_t, size_t)>::Type == 
       size_t(size_t, size_t, size_t) 
2

Đối với loại độc đoán và không chỉ size_t, chỉ cần viết một bí danh helper:

template<class T, size_t> 
using Type = T; 

template<std::size_t... S> 
struct AHelper<std::index_sequence<S...>> { 
    std::function<size_t(Type<MyArbitraryTypeHere, S>...)> foo; 
}; 
Các vấn đề liên quan