task_array<n> and variadic templates

Hi, I want to create an static task_array<n> which must be initiaized with n functors. In pseudo code: template <std::size N> struct task_array { template <typename F_1, ..., typename F_N> task_array(F_1 f1, ..., F_N fN); }; My current implementation with N=1..3 is like that template <std::size N> struct task_array; template <> struct task_array<1>; { template <typename F_1,> task_array(F_1 f1); }; template <> struct task_array<2>; { template <typename F_1, typename F_2> task_array(F_1 f1, F_2 f2); }; template <> struct task_array<3>; { template <typename F_1, typename F_2, typename F_3> task_array(F_1 f1, F_2 f2, F_3 f3); }; I can use the Boost.Preprocessor library to generate this up to a maximum know at compile time, but can I define this class with the help of variadic templates? If yes how? Thanks in advance, Vicente

On Wed, Nov 19, 2008 at 3:18 AM, vicente.botet <vicente.botet@wanadoo.fr>wrote:
Hi,
I want to create an static task_array<n> which must be initiaized with n functors.
In pseudo code:
template <std::size N> struct task_array { template <typename F_1, ..., typename F_N> task_array(F_1 f1, ..., F_N fN); };
You could use a normal variadic template constructor with a static_assert in it. If that's not good enough (i.e. you need to remove the constructor from the overload set) I would suggest enable_if, but I can't think of a way to get it into the constructor. With concepts you could do requires std::True<sizeof...(T) == N> Yechezkel Mett

----- Original Message ----- From: "Yechezkel Mett" <ymett.on.boost@gmail.com> To: <boost@lists.boost.org> Sent: Wednesday, November 19, 2008 11:02 AM Subject: Re: [boost] task_array<n> and variadic templates
On Wed, Nov 19, 2008 at 3:18 AM, vicente.botet <vicente.botet@wanadoo.fr>wrote:
Hi,
I want to create an static task_array<n> which must be initiaized with n functors.
In pseudo code:
template <std::size N> struct task_array { template <typename F_1, ..., typename F_N> task_array(F_1 f1, ..., F_N fN); };
You could use a normal variadic template constructor with a static_assert in it.
Ok, I see. template <std::size N> struct task_array { template <typename... F> task_array(F... f) { static_assert(sizeof...(T) == N, "Constructor must provide N parameters"); }; I can use Boost.StaticAssert or Boost.Mpl for that.
If that's not good enough (i.e. you need to remove the constructor from the overload set) I would suggest enable_if, but I can't think of a way to get it into the constructor. With concepts you could do
requires std::True<sizeof...(T) == N>
This is really coul template <std::size N> struct task_array { template <typename... F> task_array(F... f) requires std::True<sizeof...(T) == N>; }; Comming back to my example, I need to store the tasks on an array. I do it now like this: template <> struct task_array<3> { task arr_[3]; template <typename F_1, typename F_2, typename F_3> task_array(F_1 f1, F_2 f2, F_3 f3) { arr_[0]=task(f1); arr_[1]=task(f2); arr_[2]=task(f3); } }; I don't see a simple way to do it with variadic templates other than recursion. Is there a simple way to achieve this something like template <std::size N> struct task_array { task arr_[N]; template <typename... F> task_array(F... f) { static_assert(sizeof...(T) == N, "Constructor must provide N parameters") { arr_={task(f)...}; } }; Thanks, Vicente

On Wed, Nov 19, 2008 at 5:08 PM, Vicente Botet <vicente.botet@wanadoo.fr> wrote:
Comming back to my example, I need to store the tasks on an array. I do it now like this:
template <> struct task_array<3> { task arr_[3]; template <typename F_1, typename F_2, typename F_3> task_array(F_1 f1, F_2 f2, F_3 f3) { arr_[0]=task(f1); arr_[1]=task(f2); arr_[2]=task(f3); } };
I don't see a simple way to do it with variadic templates other than recursion.
Is there a simple way to achieve this something like
template <std::size N> struct task_array { task arr_[N]; template <typename... F> task_array(F... f) { static_assert(sizeof...(T) == N, "Constructor must provide N parameters") { arr_={task(f)...}; } };
Recursion is the way to do anything with variadic templates :-) But the following should work in theory: template <std::size N> struct task_array { task arr_[N]; template <typename... F> task_array(F... f) : arr_({task(f)...}) { static_assert(sizeof...(T) == N, "Constructor must provide N parameters") } }; if you can find a compiler that supports the new initialisation syntax, that is. Yechezkel Mett

On Wed, Nov 19, 2008 at 5:32 PM, Yechezkel Mett <ymett.on.boost@gmail.com> wrote:
On Wed, Nov 19, 2008 at 5:08 PM, Vicente Botet <vicente.botet@wanadoo.fr> wrote:
Comming back to my example, I need to store the tasks on an array. I do it now like this:
template <> struct task_array<3> { task arr_[3]; template <typename F_1, typename F_2, typename F_3> task_array(F_1 f1, F_2 f2, F_3 f3) { arr_[0]=task(f1); arr_[1]=task(f2); arr_[2]=task(f3); } };
I don't see a simple way to do it with variadic templates other than recursion.
Is there a simple way to achieve this something like
template <std::size N> struct task_array { task arr_[N]; template <typename... F> task_array(F... f) { static_assert(sizeof...(T) == N, "Constructor must provide N parameters") { arr_={task(f)...}; } };
Recursion is the way to do anything with variadic templates :-) But the following should work in theory:
template <std::size N> struct task_array { task arr_[N]; template <typename... F> task_array(F... f) : arr_({task(f)...}) { static_assert(sizeof...(T) == N, "Constructor must provide N parameters") } };
if you can find a compiler that supports the new initialisation syntax, that is.
On a current compiler: template <std::size N> struct task_array { task arr_[N]; template <typename... F> task_array(F... f) { static_assert(sizeof...(T) == N, "Constructor must provide N parameters") boost::array<task, N> arr = { task(f)... }; std::copy(arr.begin(), arr.end(), arr_); } }; if you don't mind the multiple copies -- perhaps better to move rather than copy. Recursion isn't too bad either: namespace detail { template<typename T, typename Head, typename... Tail> void fill_array(T* arr, Head h, Tail... t) { *arr = T(h); fill_array(arr + 1, t...); } template<typename T> void fill_array(T* arr) {} } template <std::size N> struct task_array { task arr_[N]; template <typename... F> task_array(F... f) { static_assert(sizeof...(T) == N, "Constructor must provide N parameters") detail::fill_array(arr_, f...); } }; Yechezkel Mett

----- Original Message ----- From: "Yechezkel Mett" <ymett.on.boost@gmail.com> To: <boost@lists.boost.org> Sent: Wednesday, November 19, 2008 4:51 PM Subject: Re: [boost] task_array<n> and variadic templates
On Wed, Nov 19, 2008 at 5:32 PM, Yechezkel Mett <ymett.on.boost@gmail.com> wrote:
On Wed, Nov 19, 2008 at 5:08 PM, Vicente Botet <vicente.botet@wanadoo.fr> wrote:
On a current compiler:
template <std::size N> struct task_array { task arr_[N]; template <typename... F> task_array(F... f) { static_assert(sizeof...(T) == N, "Constructor must provide N parameters") boost::array<task, N> arr = { task(f)... }; std::copy(arr.begin(), arr.end(), arr_); } };
if you don't mind the multiple copies -- perhaps better to move rather than copy.
Recursion isn't too bad either:
namespace detail { template<typename T, typename Head, typename... Tail> void fill_array(T* arr, Head h, Tail... t) { *arr = T(h); fill_array(arr + 1, t...); }
template<typename T> void fill_array(T* arr) {} }
template <std::size N> struct task_array { task arr_[N]; template <typename... F> task_array(F... f) { static_assert(sizeof...(T) == N, "Constructor must provide N parameters") detail::fill_array(arr_, f...); } };
I will try both, changing the c array by boos::array Thanks, Vicente

----- Original Message ----- From: "Yechezkel Mett" <ymett.on.boost@gmail.com> To: <boost@lists.boost.org> Sent: Wednesday, November 19, 2008 4:32 PM Subject: Re: [boost] task_array<n> and variadic templates
On Wed, Nov 19, 2008 at 5:08 PM, Vicente Botet <vicente.botet@wanadoo.fr> wrote:
Comming back to my example, I need to store the tasks on an array. I do it now like this:
template <> struct task_array<3> { task arr_[3]; template <typename F_1, typename F_2, typename F_3> task_array(F_1 f1, F_2 f2, F_3 f3) { arr_[0]=task(f1); arr_[1]=task(f2); arr_[2]=task(f3); } };
I don't see a simple way to do it with variadic templates other than recursion.
Is there a simple way to achieve this something like
template <std::size N> struct task_array { task arr_[N]; template <typename... F> task_array(F... f) { static_assert(sizeof...(T) == N, "Constructor must provide N parameters") { arr_={task(f)...}; } };
Recursion is the way to do anything with variadic templates :-) But the following should work in theory:
template <std::size N> struct task_array { task arr_[N]; template <typename... F> task_array(F... f) : arr_({task(f)...}) { static_assert(sizeof...(T) == N, "Constructor must provide N parameters") } };
if you can find a compiler that supports the new initialisation syntax, that is.
I was looking for confirmation. Thanks, Vicente
participants (3)
-
Vicente Botet
-
vicente.botet
-
Yechezkel Mett