|
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