Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > c++0x variadic templates

Reply
Thread Tools

c++0x variadic templates

 
 
Valeriu Catina
Guest
Posts: n/a
 
      03-13-2008
Hi,

I've programed a TinyArray class (see below) using some C++0x features
already available in g++ 4.3.0. I would be interested in your comments
about the implementation of the ()(I...) operators. The use of variadic
templates and static assertions allow an elegant programing of these
operators but there is a major inconvenience: one is able to call them
like this:

TinyArray<double,3,3> rotation_matrix;

rotation_matrix(2,1 ) = 3; // ok
rotation_matrix(2,1.3) = 3; // still ok, no waring issued





Here is the complete code:


// ================================================== ================
// ================================================== ================

// length helper: get the length (N1*N2*...*Nn) of the static array
template<size_t...N> struct hlp_length;

// length helper specialization, expansion of the parameter pack
template<size_t N1, size_t...N> struct hlp_length<N1,N...>
{
static const size_t length = N1 * hlp_length<N...>::length;
};

// length helper specialization, 1-arg param pack
template<size_t N1> struct hlp_length<N1>
{
static const size_t length = N1;
};

// ================================================== ================
// ================================================== ================

// position helper: the position of an array element
// (i1,i2,i3,...,in) ==> i1*1 + i2*stride2 + ... + in*striden,
// stride1 == 1
template<size_t...N> struct hlp_position;

// position helper specialization, expansion of the parameter pack
template<size_t N1, size_t ...N> struct hlp_position<N1,N...>
{
// stride = N2*N3*...*Nn
static const size_t stride = hlp_length<N...>::length;

template<typename...I>
static size_t get(size_t i1, I...i)
{
return i1*stride + hlp_position<N...>::get(i...);
}
};

// position helper specialization, 1-arg parameter pack
template<size_t N1> struct hlp_position<N1>
{
static size_t get(size_t i1)
{
return i1;
}
};

// ================================================== ================
// ================================================== ================

// set last element
template<int N, typename T, typename UN>
inline void hlp_populate(T* data, UN un)
{
data[N-1] = un;
}

// ================================================== ================
// ================================================== ================

// set array elements
template<int N, typename T, typename U0, typename ...U>
inline void hlp_populate(T* data, U0 u0, U ...u)
{
// write at position zero
data[N-sizeof...(U)-1] = u0;
// recursive call, write at positions 1,2,3,...,N-1
hlp_populate<N,T,U...>(data,u...);
}

// ================================================== ================
// ================================================== ================

// array class
template<typename T, size_t...N> class TinyArray;

// array class specialization, expansion of the parameter pack
template<typename T, size_t N1, size_t...N>
class TinyArray<T,N1,N...>{

public:
static const size_t size = hlp_length<N1,N...>::length;

public:

// constructor
TinyArray() { }

// constructor, initialize array elements
template<typename ...U> explicit TinyArray(U ...u)
{
// check number of arguments
static_assert(size == sizeof...(U),
"TinyArray<T,N...>::TinyArray(U...), bad number of args");
// write values
hlp_populate<size,T,U...>(data_,u...);
}

// element position in data array
template<typename ...I>
size_t position(I... i) const
{
return hlp_position<N1,N...>::get(i...);
}

// element access, const
template<typename ...I> T operator()(I... i) const
{
// check the number of arguments
static_assert(sizeof...(I) == 1+sizeof...(N),
"TinyArray<T,N...>:perator()(I...) const, bad number of args");
// get element
return data_[position(i...)];
}

// element access, non-const
template<typename ...I> T& operator()(I... i)
{
// check the number of arguments
static_assert(sizeof...(I) == 1+sizeof...(N),
"TinyArray<T,N...>:perator()(I...), bad number of args");
// get element
return data_[position(i...)];
}


private:
// data
T data_[size];
};
 
Reply With Quote
 
 
 
 
Valeriu Catina
Guest
Posts: n/a
 
      03-13-2008
Valeriu Catina wrote:
> Hi,
>
> I've programed a TinyArray class (see below) using some C++0x features
> already available in g++ 4.3.0. I would be interested in your comments
> about the implementation of the ()(I...) operators. The use of variadic
> templates and static assertions allow an elegant programing of these
> operators but there is a major inconvenience: one is able to call them
> like this:
>
> TinyArray<double,3,3> rotation_matrix;
>
> rotation_matrix(2,1 ) = 3; // ok
> rotation_matrix(2,1.3) = 3; // still ok, no waring issued
>
>
>
>
>
> Here is the complete code:
>
>
> // ================================================== ================
> // ================================================== ================
>
> // length helper: get the length (N1*N2*...*Nn) of the static array
> template<size_t...N> struct hlp_length;
>
> // length helper specialization, expansion of the parameter pack
> template<size_t N1, size_t...N> struct hlp_length<N1,N...>
> {
> static const size_t length = N1 * hlp_length<N...>::length;
> };
>
> // length helper specialization, 1-arg param pack
> template<size_t N1> struct hlp_length<N1>
> {
> static const size_t length = N1;
> };
>
> // ================================================== ================
> // ================================================== ================
>
> // position helper: the position of an array element
> // (i1,i2,i3,...,in) ==> i1*1 + i2*stride2 + ... + in*striden,
> // stride1 == 1
> template<size_t...N> struct hlp_position;
>
> // position helper specialization, expansion of the parameter pack
> template<size_t N1, size_t ...N> struct hlp_position<N1,N...>
> {
> // stride = N2*N3*...*Nn
> static const size_t stride = hlp_length<N...>::length;
>
> template<typename...I>
> static size_t get(size_t i1, I...i)
> {
> return i1*stride + hlp_position<N...>::get(i...);
> }
> };
>
> // position helper specialization, 1-arg parameter pack
> template<size_t N1> struct hlp_position<N1>
> {
> static size_t get(size_t i1)
> {
> return i1;
> }
> };
>
> // ================================================== ================
> // ================================================== ================
>
> // set last element
> template<int N, typename T, typename UN>
> inline void hlp_populate(T* data, UN un)
> {
> data[N-1] = un;
> }
>
> // ================================================== ================
> // ================================================== ================
>
> // set array elements
> template<int N, typename T, typename U0, typename ...U>
> inline void hlp_populate(T* data, U0 u0, U ...u)
> {
> // write at position zero
> data[N-sizeof...(U)-1] = u0;
> // recursive call, write at positions 1,2,3,...,N-1
> hlp_populate<N,T,U...>(data,u...);
> }
>
> // ================================================== ================
> // ================================================== ================
>
> // array class
> template<typename T, size_t...N> class TinyArray;
>
> // array class specialization, expansion of the parameter pack
> template<typename T, size_t N1, size_t...N>
> class TinyArray<T,N1,N...>{
>
> public:
> static const size_t size = hlp_length<N1,N...>::length;
>
> public:
>
> // constructor
> TinyArray() { }
>
> // constructor, initialize array elements
> template<typename ...U> explicit TinyArray(U ...u)
> {
> // check number of arguments
> static_assert(size == sizeof...(U),
> "TinyArray<T,N...>::TinyArray(U...), bad number of args");
> // write values
> hlp_populate<size,T,U...>(data_,u...);
> }
>
> // element position in data array
> template<typename ...I>
> size_t position(I... i) const
> {
> return hlp_position<N1,N...>::get(i...);
> }
>
> // element access, const
> template<typename ...I> T operator()(I... i) const
> {
> // check the number of arguments
> static_assert(sizeof...(I) == 1+sizeof...(N),
> "TinyArray<T,N...>:perator()(I...) const, bad number of args");
> // get element
> return data_[position(i...)];
> }
>
> // element access, non-const
> template<typename ...I> T& operator()(I... i)
> {
> // check the number of arguments
> static_assert(sizeof...(I) == 1+sizeof...(N),
> "TinyArray<T,N...>:perator()(I...), bad number of args");
> // get element
> return data_[position(i...)];
> }
>
>
> private:
> // data
> T data_[size];
> };



Got it. Added:

template<typename I> struct hlp_get_index;

#define DECL_GET_INDEX(T) \
template<> struct hlp_get_index<T> { static inline T get(T i) { return
i; } };

// specialize hlp_get_index for valid index types
DECL_GET_INDEX(char)
DECL_GET_INDEX(unsigned char)
DECL_GET_INDEX(short int)
DECL_GET_INDEX(unsigned short int)
DECL_GET_INDEX(int)
DECL_GET_INDEX(unsigned int)
DECL_GET_INDEX(long)
DECL_GET_INDEX(unsigned long int)

#undef DECL_GET_INDEX


and modified hlp_position to:



// position helper: the position of an array element
// (i1,i2,i3,...,in) ==> i1*1 + i2*stride2 + ... + in*striden, stride1 == 1
template<size_t...N> struct hlp_position;

// position helper specialization, expansion of the parameter pack
template<size_t N1, size_t ...N> struct hlp_position<N1,N...>
{
// stride = N2*N3*...*Nn
static const size_t stride = hlp_length<N...>::length;

template<typename I1, typename...I>
static I1 get(I1 i1, I...i)
{
return hlp_get_index<I1>::get(i1)*stride +
hlp_position<N...>::get(i...);
}
};

// position helper specialization, 1-arg parameter pack
template<size_t N1> struct hlp_position<N1>
{
template<typename I>
static I get(I i)
{
return hlp_get_index<I>::get(i);
}
};

Now a call like:

TinyArray<some_type,3,2,5> a;

a(3,2,1.13,2) will generate an error message (not a very friendly one
though) related to the instantiation of the incomplete type
hlp_get_index<double>.








 
Reply With Quote
 
 
 
 
Erik Wikström
Guest
Posts: n/a
 
      03-13-2008
On 2008-03-13 16:33, Valeriu Catina wrote:
> Hi,
>
> I've programed a TinyArray class (see below) using some C++0x features
> already available in g++ 4.3.0. I would be interested in your comments
> about the implementation of the ()(I...) operators. The use of variadic
> templates and static assertions allow an elegant programing of these
> operators but there is a major inconvenience: one is able to call them
> like this:
>
> TinyArray<double,3,3> rotation_matrix;
>
> rotation_matrix(2,1 ) = 3; // ok
> rotation_matrix(2,1.3) = 3; // still ok, no waring issued


I do not know how variadic templates and concepts play together but I
imagine that in the future you will want to limit the types to those
matching the Integram (or perhaps UnsignedIntegral) concept.

--
Erik Wikström
 
Reply With Quote
 
Erik Wikström
Guest
Posts: n/a
 
      03-13-2008
On 2008-03-13 18:09, Erik Wikström wrote:
> On 2008-03-13 16:33, Valeriu Catina wrote:
>> Hi,
>>
>> I've programed a TinyArray class (see below) using some C++0x features
>> already available in g++ 4.3.0. I would be interested in your comments
>> about the implementation of the ()(I...) operators. The use of variadic
>> templates and static assertions allow an elegant programing of these
>> operators but there is a major inconvenience: one is able to call them
>> like this:
>>
>> TinyArray<double,3,3> rotation_matrix;
>>
>> rotation_matrix(2,1 ) = 3; // ok
>> rotation_matrix(2,1.3) = 3; // still ok, no waring issued

>
> I do not know how variadic templates and concepts play together but I
> imagine that in the future you will want to limit the types to those
> matching the Integram (or perhaps UnsignedIntegral) concept.


s/Integram/Integral/

--
Erik Wikström
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Call again a variadic function (... variable number of arguments)with same arguments that its variadic wrapper moreau.steve@gmail.com C Programming 3 12-31-2008 07:13 AM
variadic function calling variadic function goldfita@signalsguru.net C Programming 5 05-03-2006 05:23 PM
Using variadic functions within variadic functions pinkfloydhomer@gmail.com C Programming 2 02-27-2006 05:47 AM
Variadic functions calling variadic functions with the argument list, HLL bit shifts on LE processors Ross A. Finlayson C Programming 19 03-10-2005 03:57 AM
is casting a variadic function to a non-variadic one legal? Colin Walters C Programming 2 02-13-2004 10:55 PM



Advertisments