【问题标题】:Problems using mpl::if_, boost::function, and a typedef to void使用 mpl::if_、boost::function 和 typedef 来 void 的问题
【发布时间】:2011-11-24 14:01:39
【问题描述】:

我是 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_ 的选定部分....

【问题讨论】:

  • 我收到'result_type' in namespace 'boost::function_types' does not name a type
  • P 没有在TTT 声明中使用,这是正常的还是错字(我们不知道您要达到什么目的,所以很难说)?
  • 为什么反对票和接近票?这是一个完全合理的问题,可以回答并且可以帮助其他人。它让我了解到在参数列表中使用 typedef 来 void 是一个错误,这似乎是该问题的充分理由:)。它可以帮助使用 MPL 和/或 boost/std::function 的其他人。也许可以改写标题,因为问题不是关于function_types,而是更多关于function 和一般的函数签名。

标签: c++ boost metaprogramming boost-function boost-mpl


【解决方案1】:

首先要说明错误,需要注意的是,在参数列表中对void使用typedef是错误的。这两个 GCC 错误报告(320589278)描述了这个问题,并指出这是标准的要求。

所以基本上,根据标准的§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) 永远不会出现。

更好的解决方案甚至是为 void 案例专门化 get_function 元函数:

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_

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-14
    • 1970-01-01
    相关资源
    最近更新 更多