Sign in to follow this  

Unity variable no. of template argument - possible solution

This topic is 4524 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

After reading over my recent thread about virtual templates a passage (at the bottom) by MaulingMonkey got me thinking and after a little tinkering I found a way to have a variable number of template arguments. Its not exactly what I would call flexible and may not be useful for all circumstaces but it does work (I only wanted to see if I could achieve the task.) The technique requires (well not 'requires' but works better with) two macros and two simple meta-programs:
//USED TO INDICATE THE END OF THE ARGUMENT LIST
struct end_args;

//MACRO TO BEGIN THE VARARG LIST
#define template_varags(name) template <int i = 1>struct name{    typedef end_args next;};

//MACRO TO ADD A PARAMETER
#define param(to, num, t, val) template <>struct to<num>{    typedef to<num+1> next;    typedef t type;    static type value() { return val; }};

//META-PROGRAM TO FIND THE NUMBER OF PARAMETERS
template <class T, int i = 0>
struct num_args
{
    enum { result = num_args<typename T::next, i + 1>::result };
};

template <int i>
struct num_args<end_args, i> //SPECIALIZATION TO END RECURSION
{
    enum { result = i-1 };
};

//META-PROGRAM TO RETURN THE VALUE OF AN ARGUMENT
template<class T, int i>
struct get_arg
{
    typedef typename get_arg<typename T::next, i-1>::type type;
    static type get() { return get_arg<typename T::next, i-1>::get(); }
};

template <class T>
struct get_arg<T, 0> //SPECIALIZATION TO END RECURSION
{
    typedef typename T::type type;
    static type get() { return T::value(); }
};
Ok, now with that you can create templates with variable number of arguments. A program to output all the variable values to the console might look like this:
template <class T, int i = num_args<T>::result - 1>
struct print
{
    static void invoke()
    {
        cout << get_arg<T, (num_args<T>::result - 1) - i>::get() << endl;
        print<T, i-1>::invoke();
    }
};

template <class T>
struct print<T, 0>
{
    static void invoke()
    {
        cout << get_arg<T, num_args<T>::result - 1>::get() << "\n\n";
    }
};

//CREATE THE VARARG LIST (could go in a namespace to reduce name pollution)
template_varags(args)
    param(args, 0, int, 5)
    param(args, 1, float, 4.5)
    param(args, 2, char, 'z')

int main()
{
    cout << "num parameters: " << num_args<args<0> >::result << endl;
    cout << "\nall parameter values:\n";
    print <args<0> >::invoke();

    return 0;
}
I'm certain that someone else here can create a much more powerful way to acieve variable argument templates, but I'm curious for comments/pitfalls. Dave [Edited by - dmatter on August 29, 2005 3:03:44 PM]

Share this post


Link to post
Share on other sites
It's related, but you might also look into the book Modern C++ Design. It's basically about the Loki libraries and how it works.

Share this post


Link to post
Share on other sites
Quote:
Original post by Rattrap
Try this Loki. Loki has a Template List that might be what you are looking for.


I recommend boost MPL, its much powerful than loki's type lists and provides complete analogues (and more) of C++ standard library containers (vector, list, set etc) & algorithms in land of compile-time. Boost MPL completely formalized template metaprogramming making it easy and fun to write metaprograms. Throw in a combo of Boost.Preprocessor and the sky's the limit [grin].

Share this post


Link to post
Share on other sites
Quote:
Original post by snk_kid
Boost MPL completely formalized template metaprogramming making it easy and fun to write metaprograms.


Your Mileage May Vary. Void Where Prohibited. No Purchase Necessary. Do Not Taunt Happy Fun Ball. MPL Is An Equal Opportunity Employer.

Share this post


Link to post
Share on other sites
Rule one of MPL is you do not expect MPL to be fully supported by your compiler. Rule two of MPL is YOU DO NOT EXPECT MPL TO BE FULLY SUPPORTED BY YOUR COMPILER!

Share this post


Link to post
Share on other sites
Sign in to follow this