I’m new to the Boost.MPL library, and have some “beginners-problems”
Look at this sample:
template < typename F >
struct A {
typedef boost::function_types::parameter_types<F> P;
typedef typename boost::function_types::result_type<F>::type R;
typedef typename boost::mpl::if_< boost::is_same< R, void >,
boost::function< void ( void ) > ,
boost::function< void ( R ) > >::type TTT;
A() { }
};
int main(int argc, const char *argv[]) {
A<int(int, float)> ok; // working
A<void(int, float)> compile_error; // non-working
return 0;
}
When compiling I get:
xxx.cxx: In instantiation of ‘A<void(int, float)>’:
xxx.cxx:108:25: instantiated from here
xxx.cxx:100:77: error: invalid parameter type
‘boost::mpl::aux::wrapped_type<boost::mpl::aux::type_wrapper<void>
>::type’
xxx.cxx:100:77: error: in declaration ‘A<F>::TTT’
What is the problem here, and how can I solve it?
To my understanding, only the selected part of mpl::if_ should be evaluated by the compiler….
First of all, to explain the error, it should be noted that using a typedef to
voidin a parameter list is an error. These two GCC bug reports (32058 and 9278) describe the problem, an point out that this is requirement from the standard.So basically, according to §8.3.5/2 of the standard, this is legal:
while this is not:
This explains why you needed the
if_in the first place. Now to explain why you still have the error, you need to understand that lazy evaluation in MPL only apply to metafunctions: as long as you don’t access thetypeinside a metafunction, it is not evaluated. Here, theif_‘s arguments are not evaluated (they could not since they are not metafunctions), but that does not mean that they are not instantiated.To overcome this issue, you could embed the
functioninstantiations into metafunctions that could be lazily evaluated:This way, the erroneous
void (typedef_to_void)never appears.A better solution would even be to specialize the
get_functionmetafunction for thevoidcase:No more
if_needed!