Boost logo

Boost :

From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2002-04-17 00:48:38


> Issue: passing argument types to the function object wrapper
[...]
> On the flip side, I personally still prefer the individual template
> parameters. They feel like a more obvious translation from function types to
> function object wrapper types. Functor<void, TYPELIST_3(int, float, double)>
> bothers me for some reason, and aesthetically I prefer Functor<void, int,
> float, double> (this could be the bias of seeing the latter very often).

This can easily be altered. I don't think anybody--even Andrei--would want
those macros. :) There is an easy solution to this problem:

// basic typelist

template<class T, class U = null_t> struct typelist_t {
    typedef T head;
    typedef T tail;
};

// facility to get the 'number' out of the name
// which is very favorable for meta-programming

template<int> struct typelist;

template<> struct typelist<1> {
    template<class T1> struct args {
        typedef typelist_t<T1> type;
    };
};

template<> struct typelist<2> {
    template<class T1, class T2 = T1> struct args {
        typedef typelist_t<T1, typename typelist<1>::args<T2>::type> type;
    };
};

template<> struct typelist<3> {
    template<class T1, class T2 = T1, class T3 = T2> struct args {
        typedef typelist_t<T1, typename typelist<2>::args<T2, T3>::type> type;
    };
};

// etc. (these specializations can be generated with the preprocessor library)

Now you have: 'typelist<3>::args<int, float, double>'
which is slightly better than TYPELIST_3(int, float, double).

In addition, you can define a general purpose extraction utility:

// utility to extract the function parameter types into a template
// with signature: placeholder< int >::args< types >

template<class func_t, template<int> class output> struct extract;

template<class R, class T1, template<int> class output>
struct extract<R (T1), output> {
    typedef typename output<1>::template args<T1>::type type;
};

template<class R, class T1, class T2, template<int> class output>
struct extract<R (T1, T2), output> {
    typedef typename output<2>::template args<T1, T2>::type type;
};

// etc. (this also can be generated with the preprocessor library)

Ultimately, you can get rid of the 'unsightly' number '3':
#define TYPELIST(args) extract<void args, typelist>::type

Which could be used like this:
Functor<void, TYPELIST((int, float, double))>

If we get _VA_ARGS_ from C99 in the C++0x standard, it could be reduced to
single parenthesis:
#define TYPELIST(...) extract<void (args), typelist>::type

If you did the same type of thing for tuples, you could use the default
arguments to 'clean' stuff up a bit:

tuple<3>::args<int> get_3d_point(int x, int y, int z) {
    return tuple<3>::args<int>(x, y, z);
}

> The situation would be much different for me if there were a direct
> translation from a typelist facility to a function declaration/definition in
> the language. For instance, if we were able to create a function like:
>
> void foo(TYPELIST_4(int, float, double, std::string)) { /* ... */ }
>
> and access the members of the typelist in some simple fashion at run-time,
> then the idea of packaging all of the arguments in a typelist would be more
> natural in C++. I think I would then support a changeover to that method.
> - Proposed resolution: No change at this time.

What do you mean? Loki has a tuple facility that is easy to use. If you
actually mean using typelists to create a function-declaration like this:

void foo(int a, float b, double c, std::string d);

...That is possible, but I don't know of a way to 'define' a function that
way--since you can't define a function with a typedef.

..my comments. :)

Paul Mensonides


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk