2
4

2 回答 2

4

正如你在这里看到的:

转换通常采用 proto::when<Something, R(A0,A1,...) > 的形式。问题是 R 是表示要调用的函数还是要构造的对象,答案决定了 proto::when<> 如何评估转换。proto::when<> 使用 proto::is_callable<> 特征来消除两者之间的歧义。Proto 会尽力猜测一个类型是否是可调用的,但它并不总是正确的。最好了解 Proto 使用的规则,以便您知道何时需要更明确。

对于大多数类型 R,proto::is_callable 检查是否从 proto::callable 继承。但是,如果类型 R 是模板特化,Proto 假定它是不可调用的,即使模板继承自 proto::callable。

该文档提出了解决方案:您要么包装每次调用do_eval<double>with ,proto::call要么只是is_callable在 boost::proto 命名空间中进行专门化,然后忘记问题。

namespace boost { namespace proto
{
    // Tell Proto that do_eval2<> is callable
    template<typename T>
    struct is_callable<do_eval2<T> >
      : mpl::true_
    {};
}}

[编辑:]这是proto::call替代方案:

struct eval2
  : proto::or_<
      proto::when<proto::terminal<proto::_>, proto::_value>
    , proto::otherwise<
        proto::call<do_eval2<double>(proto::tag_of<proto::_>(),
                                     eval2(proto::pack(proto::_))...)>>
    >
{};
于 2013-04-30T19:07:23.823 回答
4

请参阅上一个答案。我还要补充一点,另一个解决方案是这样定义do_eval2

template <typename T, typename D = proto::callable>
struct do_eval2 : proto::callable
{
  typedef T result_type;
  template <typename X, typename Y>
  result_type operator()(proto::tag::plus, X x, Y y) const { return x + y; }
};

请注意额外的虚拟模板参数。

编辑:此外,在目前正在开发的 Proto 的下一个版本中,您不需要了解这件奥秘,事情应该只是工作。几周后我将在 C++Now 上讨论它。

于 2013-05-01T15:22:49.960 回答