Sign in to follow this  
RealMarkP

[C++] Variable Template Parameters

Recommended Posts

I'm curious, is there anyway to actually do this? I would like to have a templated class with variable amount of Template parameters:
template<class T, ...>
class foo
{
  T x;
  /// etc...

};


Or would I have to specify a template class for a static number of template parameters. I had a look at the tuple code from boost and they manually speciy up to 10 parameters. It seems very repetative. Any thoughts?

Share this post


Link to post
Share on other sites
It's a native feature of the language in C++0x, the next version of the standard which isn't completed yet. If you use a recent version of GCC, it probably already supports this by using the command line option to enable C++0x features.

Otherwise, you're out of luck. Boost uses variadic templates in a number of places, but in all cases you're limited to a compile time constant number of template parameters, and they hack it together using preprocessor magic.

Share this post


Link to post
Share on other sites
If you want to hack it together up to a predefined maximum number of parameters, the easiest way of doing it (unless you want to learn how to use Boost.Preprocessor, which is no easy feat) is by making a dummy class called 'nop', and then using template specializations for various numbers of nops. For example, here's a class template that takes 3, 4, 5, or 6 args.


template<class T, class U, class V, class A1=nop, class A2=nop, class A3=nop>
class Foo : public FooConfig<T,U,V,A1,A2,A3>{};

template<class T, class U, class V, class A1, class A2, class A3>
class FooConfig {};

//This specialization is instantiated if used with 3 arguments
template<class T, class U, class V>
class FooConfig <T,U,V,nop,nop,nop>
{
};


//This specialization is instantiated if used with 4 arguments
template<class T, class U, class V, class A1>
class FooConfig <T,U,V,A1,nop,nop>
{
};


//This specialization is instantiated if used with 5 arguments
template<class T, class U, class V, class A1, class A2>
class FooConfig <T,U,V,A1,A2,nop>
{
};

//This specialization is instantiated if used with 6 arguments
template<class T, class U, class V, class A1, class A2, class A3>
class FooConfig <T,U,V,A1,A2,A3>
{
};





Obviously all versions are going to share a lot of common functionality, so FooConfig just defines a common set of typedefs that can be used by Foo.

This can be automated with Boost.Preprocessor as mentioned so that you can do something like


#define MAX_FOO_ARGS 50




and then it will do all this work for you, but it's beyond my ability so I wouldn't be able to help you with that :(

Share this post


Link to post
Share on other sites
How verbose this has to be depends greatly on what you intend to do with the template parameters within the class. If you simply need the ability to iterate across a set of types, you can do that fairly easily using boost::mpl and BOOST_PP:

#define MAX_PARAMS <N>

struct none;

template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(MAX_PARAMS, typename Param, none)>
class foo
{
typedef typename boost::mpl::remove_if
<
typename boost::mpl::vector<BOOST_PP_ENUM_PARAMS(MAX_PARAMS, Param)>::type,
boost::is_same<boost::mpl::_1, none>
>::type parameters;
};





Once you have the parameters mpl::vector, you can use all the normal MPL algorithms to get the parameters you need. For instance the third template parameter (if applicable) would be:

typename boost::mpl::at_c<parameters, 2>::type




If you need to store a set of objects based on these parameters, you might want to look into boost::fusion. If you for instance wanted to store one instance of every parameter, you could use a fusion::vector:

typedef typename boost::fusion::result_of::as_vector<parameters>::type instance_vector;
instance_vector instances;




The third instance would then be:

boost::fusion::at_c<2>(instances)




Hope that helps.

EDIT: Forgot setting the default type.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this