 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Earl Purple Guest
|
Posted: Mon Aug 21, 2006 5:49 pm Post subject: variadic templates |
|
|
If variadic templates are brought into the standard, would it allow a
"fix" to this problem.
I have in my code templates that look like this (I've snipped a lot of
the detail I'd rather not reveal, it doesn't hide what I do that is
significant to this post and what I'd like to address)
template < typename TYPE, typename PARAM1, typename PARAM2, typename
PARAM3, typename BASE=TYPE >
class Builder3Params /* cut some detail */
{
protected:
typename ParamBinder<PARAM1>::binder_type binder1;
typename ParamBinder<PARAM2>::binder_type binder2;
typename ParamBinder<PARAM3>::binder_type binder3;
public:
/* more snip */
void bindParams( /*fixed set of params for every instantiation*/)
{
/* more snip which declares and fills res */
binder1.bind( theObjectLoader, res[0] );
binder2.bind( theObjectLoader, res[1] );
binder3.bind( theObjectLoader, res[2] );
}
protected:
BASE * createObject() const
{
return new TYPE( binder1.obj(), binder2.obj(), binder3.obj() );
}
};
The purpose is to build an object of type TYPE that derives from BASE
and takes 3 parameters in its construction.
unfortuntely this is just one of 9 such templates, I have them going up
to 9 parameters (as well as a template for 0 parameters).
It would be nice to be able to do all this with just one template
definition for N parameters. And I'd like to do so where TYPE having a
constructor that takes 3 parameters in this case, of type PARAM1,
PARAM2, PARAM3.
In an variadic-parameter case, the programmer would, of course, have to
supply the correct parameter list in this instance with the correct
number of parameters and the correct types. I assumed that is what
variadic parameters were supposed to do but couldn't see any example of
this in the report. Now for the programmer to specify the number of
parameters is not a major deal - we know when we use this template
which one we are using. It is simply from the point of view of
maintaining the library - one template is better than 9 (or 10) and
would be "finalised" so there will never be a need for me to write
instantiations that take 10, 11, 12 etc parameters should they be
required.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Gene Bushuyev Guest
|
Posted: Tue Aug 22, 2006 2:28 am Post subject: Re: variadic templates |
|
|
"Earl Purple" <earlpurple (AT) gmail (DOT) com> wrote in message
news:1156178144.238727.142620 (AT) m79g2000cwm (DOT) googlegroups.com...
| Quote: | If variadic templates are brought into the standard, would it allow a
"fix" to this problem.
I have in my code templates that look like this (I've snipped a lot of
the detail I'd rather not reveal, it doesn't hide what I do that is
significant to this post and what I'd like to address)
template < typename TYPE, typename PARAM1, typename PARAM2, typename
PARAM3, typename BASE=TYPE
class Builder3Params /* cut some detail */
[...]
unfortuntely this is just one of 9 such templates, I have them going up
to 9 parameters (as well as a template for 0 parameters).
It would be nice to be able to do all this with just one template
definition for N parameters. And I'd like to do so where TYPE having a
constructor that takes 3 parameters in this case, of type PARAM1,
PARAM2, PARAM3.
|
The easy solution to that problem is writing a simple few lines program for
automatically generating code. It will also be easier for a programmer to reason
about the design and to debug it, and it works with not so smart compilers as
well. I have a number of solutions that automatically generate code at the
pre-build stage and that proved to work very well.
I think it's time to standardize the facilities to execute code generators
during compilation, that would make it easily portable to all platforms.
--
Gene Bushuyev (www.gbresearch.com)
----------------------------------------------------------------
To see what is in front of one's nose needs a constant struggle ~ George Orwell
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Douglas Gregor Guest
|
Posted: Tue Aug 22, 2006 4:20 pm Post subject: Re: variadic templates |
|
|
Earl Purple wrote:
| Quote: | If variadic templates are brought into the standard, would it allow a
"fix" to this problem.
I have in my code templates that look like this (I've snipped a lot of
the detail I'd rather not reveal, it doesn't hide what I do that is
significant to this post and what I'd like to address)
|
Yes, it's possible to use variadic templates to create a single
"BuilderParams" class template that eliminates the redundant code
below. I'm going to slice 'n' dice the code, showing how to transform
each chunk to use variadic templates.
| Quote: | template < typename TYPE, typename PARAM1, typename PARAM2, typename
PARAM3, typename BASE=TYPE
class Builder3Params /* cut some detail */
|
This can become:
template<typename TYPE, typename BASE, typename... PARAMS>
class BuilderParams
I've moved "BASE" before "PARAMS" because PARAMS is a template
parameter pack, and therefore needs to be at the end of the template
parameter list.
| Quote: | {
protected:
typename ParamBinder<PARAM1>::binder_type binder1;
typename ParamBinder<PARAM2>::binder_type binder2;
typename ParamBinder<PARAM3>::binder_type binder3;
|
I typically use tuples for storing multiple values, like this:
tuple<typename ParamBinder<PARAMS>::binder_type...> binders;
| Quote: | public:
/* more snip */
void bindParams( /*fixed set of params for every instantiation*/)
{
/* more snip which declares and fills res */
binder1.bind( theObjectLoader, res[0] );
binder2.bind( theObjectLoader, res[1] );
binder3.bind( theObjectLoader, res[2] );
}
|
The best way to do this is (probably!) with a "for_each" that works on
tuples, applying a function object to each value in the tuple. It's not
currently in the tuple library, but it's been used in various places.
For our purposes, we would write:
struct do_bind {
/* put theObjectLoader and res here */
int res_idx;
do_bind(/*inits*/) : /*inits*/, res_idx(0) { }
template<typename Binder>
void operator()(Binder& binder) {
binder.bind(theObjectLoader, res[res_idx++]);
}
};
bindParams would look like this:
void bindParams( /*fixed set of params for every instantiation*/)
{
/* more snip which declares and fills res */
for_each(binders, do_bind(theObjectLoader, res));
}
| Quote: | protected:
BASE * createObject() const
{
return new TYPE( binder1.obj(), binder2.obj(), binder3.obj() );
}
|
Implementing this is a two-step process. The technique is described
fully in the "Bind" implementation of the variadic templates proposal,
so I'll reproduce the code here without too much comment. It's rather
long at the moment, but make_indexes would typically be factored out:
// Used to store a parameter pack of integers
template<int...> struct int_tuple {};
// make_indexes_impl is a helper for make_indexes
template<int I, typename IntTuple, typename... Types>
struct make_indexes_impl;
template<int I, int... Indexes, typename T, typename... Types>
struct make_indexes_impl<I, int_tuple<Indexes...>, T, Types...>
{
typedef typename make_indexes_impl<I+1,
int_tuple<Indexes..., I>,
Types...>::type type;
};
template<int I, int... Indexes>
struct make_indexes_impl<I, int_tuple<Indexes...> > {
typedef int_tuple<Indexes...> type;
};
// Metafunction that generates an int_tuple<0, 1, 2, /* up to */ N-1>,
where N is the number of types in Types
template<typename... Types>
struct make_indexes : make_indexes_impl<0, int_tuple<>, Types...> { };
Now to the actual interesting part. The "real work" shows up in
doCreateObject, where we extract the binders from each element of the
tuple, call their .obj() methods, and use the results as arguments to
the TYPE constructor:
template<int... Indexes>
BASE * doCreateObject(int_tuple<Indexes...>) const
{
return new TYPE( get<Indexes>(binders).obj()... );
}
BASE* createObject() const
{
return doCreateObject(typename make_indexes<PARAMS...>::type());
}
I'm not very happy with the need for "doCreateObject". We're currently
discussing adding a feature that would make extracting values from a
tuple *much* easier, collapsing all of this code down to:
BASE* createObject() const
{
enum { N = sizeof(PARAMS...) };
return new TYPE( get<0..N-1>(binders).obj()... );
}
Aside from the fact that we've moved "BASE" to the second parameter
(instead of the last), the variadic templates-based BuilderParams would
work the same way as your BuilderNParams class templates. No code
repetition required.
Cheers,
Doug
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
sharon.galtzur@gmail.com Guest
|
Posted: Thu Aug 31, 2006 2:56 am Post subject: Re: variadic templates |
|
|
If i understand what u want is some means to generate lines like:
template <A0> f(A0 a0)
template <A0,A1> f(A0 a0, A1 a1) .... etc up to some configurable N
If that the case i would suggest you check boost preprocessor library.
This amazing library allow u to right meta-preprocessor which basically
allows you to do these kind of magic with c++ macros.
The advantage is that you dont need special external program but its
all done right in the compiler.
Regards,
Sharon Galtzur ]
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
Earl Purple Guest
|
Posted: Tue Sep 05, 2006 4:00 pm Post subject: Re: variadic templates |
|
|
sharon.galtzur (AT) gmail (DOT) com wrote:
| Quote: | If i understand what u want is some means to generate lines like:
template <A0> f(A0 a0)
template <A0,A1> f(A0 a0, A1 a1) .... etc up to some configurable N
If that the case i would suggest you check boost preprocessor library.
This amazing library allow u to right meta-preprocessor which basically
allows you to do these kind of magic with c++ macros.
The advantage is that you dont need special external program but its
all done right in the compiler.
|
Actually, what happens in reality above is that a type parameter T
becomes shared_ptr<T> when passed in the constructor of the object it
is creating, unless T is of a basic type (which includes string) in
which case it is passed in by value.
In the case that T is not a basic type, it looks up the name in a table
and checks that it is of the correct type and the obj() function that
is called actually invokes createObject().
In the case that T is a basic type, it simply does a lexical
conversion.
The Binder classes are specialised templates that ensure the correct
behaviour is done for each parameter type.
My question has been answered above satisfactorily, and I await
variadic templates in the standard so I can implement as above.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ] |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|