2 回答
正如你在这里看到的:
转换通常采用 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::_))...)>>
>
{};
请参阅上一个答案。我还要补充一点,另一个解决方案是这样定义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 上讨论它。