Прежде всего, чтобы объяснить ошибку, следует отметить, что использование 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_
необходимо!