I have the following code :
template<size_t sz,typename T=float> class Vec{
T v[sz];
Vec(const T& val,const T&... nv){
//how do i assign `sz` number of first arguments into `this->v` array
}
}
I want to create constructor, that receive generic number of constructor argument, and assign the first sz
number of arguments into member variable of v
what I want to do, is to be able doing like this: Vec<3> var(1.0,2.0,3.0);
This is possible, but complicated. Here is some code that does it. It may be possible to eliminate the holder
type, but I leave that as an exercise for the reader. This has been tested with g++ 4.6.
#include <iostream>
#include <typeinfo>
template<size_t ... Indices> struct indices_holder
{};
template<size_t index_to_add,typename Indices=indices_holder<> >
struct make_indices_impl;
template<size_t index_to_add,size_t...existing_indices>
struct make_indices_impl<index_to_add,indices_holder<existing_indices...> >
{
typedef typename make_indices_impl<
index_to_add-1,
indices_holder<index_to_add-1,existing_indices...> >::type type;
};
template<size_t... existing_indices>
struct make_indices_impl<0,indices_holder<existing_indices...> >
{
typedef indices_holder<existing_indices...> type;
};
template<size_t max_index>
typename make_indices_impl<max_index>::type make_indices()
{
return typename make_indices_impl<max_index>::type();
}
template<unsigned index,typename ... U>
struct select_nth_type;
template<unsigned index,typename T,typename ... U>
struct select_nth_type<index,T,U...>
{
typedef typename select_nth_type<index-1,U...>::type type;
static type&& forward(T&&,U&&... u)
{
return select_nth_type<index-1,U...>::forward(static_cast<U&&>(u)...);
}
};
template<typename T,typename ... U>
struct select_nth_type<0,T,U...>
{
typedef T type;
static type&& forward(T&&t,U&&...)
{
return static_cast<T&&>(t);
}
};
template<unsigned index,typename ... U>
typename select_nth_type<index,U...>::type&& forward_nth(U&&... u)
{
return static_cast<typename select_nth_type<index,U...>::type&&>(
select_nth_type<index,U...>::forward(
static_cast<U&&>(u)...));
}
template<size_t sz,typename T=float> struct Vec{
struct holder
{
T data[sz];
};
holder v;
template<typename ... U>
struct assign_helper
{
template<size_t... Indices>
static holder create_array(indices_holder<Indices...>,Vec* self,U&&... u)
{
holder res={{static_cast<T>(forward_nth<Indices>(u...))...}};
return res;
}
};
template<typename ... U>
Vec(U&&... u):
v(assign_helper<U...>::create_array(make_indices<sz>(),this,static_cast<U&&>(u)...))
{}
};
int main()
{
Vec<3> v(1.2,2.3,3.4,4.5,5.6,7.8);
std::cout<<"v[0]="<<v.v.data[0]<<std::endl;
std::cout<<"v[1]="<<v.v.data[1]<<std::endl;
std::cout<<"v[2]="<<v.v.data[2]<<std::endl;
}
I believe this satisfies all the requirements:
template <size_t sz,typename T,typename... Args> struct Assign;
template <typename T,typename First,typename...Rest>
struct Assign<1,T,First,Rest...> {
static void assign(T *v,const First &first,const Rest&... args)
{
*v = first;
}
};
template <size_t sz,typename T,typename First,typename... Rest>
struct Assign<sz,T,First,Rest...> {
static void assign(T *v,const First &first,const Rest&... rest)
{
*v = first;
Assign<sz-1,T,Rest...>::assign(v+1,rest...);
}
};
template<size_t sz,typename T=float>
struct Vec{
T v[sz];
template <typename... Args>
Vec(const T& val,const Args&... nv){
Assign<sz,T,T,Args...>::assign(v,val,nv...);
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With