我是Boost.MPL图书馆的新手,并且有一些"初学者问题"
看看这个样本:
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;
}
编译时我得到:
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’
这里有什么问题,我该如何解决?
根据我的理解,编译器只应评估mpl::if_
的选定部分....
答案 0 :(得分:3)
首先,为了解释错误,应该注意在参数列表中使用typedef到void
是一个错误。这两个GCC错误报告(32058和9278)描述了这个问题,并指出这是标准的要求。
基本上,根据该标准的§8.3.5/ 2,这是合法的:
void foo(void);
虽然不是这样:
typedef void type;
void foo(type);
这解释了为什么您首先需要if_
。现在解释为什么你仍然有错误,你需要理解MPL中的延迟评估仅适用于元函数:只要你不访问元函数内的type
,它就不会被评估。在这里,if_
的参数不是评估的(它们不能,因为它们不是元函数),但这并不意味着它们没有被实例化。
要解决此问题,您可以将function
实例化嵌入到可以延迟评估的元函数中:
template < typename R, typename P >
struct get_function
{
typedef boost::function< R (P) > type;
};
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::mpl::identity< boost::function< void (void) > > ,
get_function< void, R >
>::type::type TTT;
A() { }
};
这样,错误的void (typedef_to_void)
永远不会出现。
更好的解决方案甚至是专门针对get_function
案例的void
元函数:
template < typename R, typename P >
struct get_function
{
typedef boost::function< R (P) > type;
};
template < typename R >
struct get_function< R, void >
{
typedef boost::function< R (void) > type;
};
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 get_function< void, R >::type TTT;
A() { }
};
不再需要if_
!