2013-02-16 79 views
2

我试图评估将元素插入到地图中的结果boost::phoenix::insert有困难。与std::map::insert类似,由boost::phoenix::insert返回的演员对象也会返回std::pair<Iterator where, bool result>。我对该对中的第二个元素感兴趣,以检查插入是否成功。说明这个问题的重度条纹下来的代码示例如下:boost :: phoenix :: insert的评估结果

#include <iostream> 
#include <boost/phoenix/fusion.hpp> 
#include <boost/phoenix/phoenix.hpp> 
#include <boost/fusion/include/all.hpp> 
#include <boost/fusion/include/std_pair.hpp> 

int main(int, char*[]) 
{ 
    namespace phx = boost::phoenix; 
    using phx::arg_names::arg1; 
    using phx::arg_names::arg2; 

    std::map<int, int> map; 
    std::pair<int, int> value(1, 2); 

    if (phx::at_c<1>(phx::insert(arg1, arg2))(map, value)) // <- Error here 
    std::cout << "Success" << std::endl; 
    else 
    std::cout << "Fail" << std::endl; 

    return 0; 
} 

我使用MSVC2012出现以下错误并提高1.53:

error C2440: 'return' : cannot convert from 'const bool' to 'bool &' 
<some-path>\include\boost\proto\transform\call.hpp:258 

clang3.2报告了同样的错误:

Compilation finished with errors: 
In file included from source.cpp:2: 
In file included from /usr/local/include/boost/phoenix/fusion.hpp:14: 
In file included from /usr/local/include/boost/phoenix/fusion/at.hpp:14: 
In file included from /usr/local/include/boost/phoenix/core/expression.hpp:10: 
In file included from /usr/local/include/boost/phoenix/core/as_actor.hpp:10: 
In file included from /usr/local/include/boost/phoenix/core/actor.hpp:17: 
In file included from /usr/local/include/boost/phoenix/core/domain.hpp:12: 
In file included from /usr/local/include/boost/proto/matches.hpp:43: 
In file included from /usr/local/include/boost/proto/transform/when.hpp:22: 
/usr/local/include/boost/proto/transform/call.hpp:255:24: error: binding of reference to type 'bool' to a value of type 'const bool' drops qualifiers 
       return typename detail::poly_function_traits<Fun, Fun(a0, a1)>::function_type()(
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/local/include/boost/phoenix/core/meta_grammar.hpp:74:24: note: in instantiation of member function 'boost::proto::call<boost::proto::functional::at (boost::phoenix::evaluator (*)(boost::proto::_child_c<1>), boost::proto::_value (*)(boost::proto::_child_c<0>))>::impl2<const boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::at_c, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<mpl_::int_<1> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list3<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::stl::insert>, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<1> >, 0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<2> >, 0> > >, 3> > >, 2> > &, boost::phoenix::vector3<const boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::at_c, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<mpl_::int_<1> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list3<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::stl::insert>, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<1> >, 0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<2> >, 0> > >, 3> > >, 2> > *, std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > > &, std::pair<int, int> &> &, const boost::phoenix::default_actions &, false>::operator()' requested here 
       return what()(e, phoenix::env(s), actions(s)); 
        ^
/usr/local/include/boost/phoenix/core/meta_grammar.hpp:34:9: note: in instantiation of member function 'boost::phoenix::evaluator::impl<const boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::at_c, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<mpl_::int_<1> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list3<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::stl::insert>, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<1> >, 0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<2> >, 0> > >, 3> > >, 2> > &, const boost::phoenix::vector2<boost::phoenix::vector3<const boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::at_c, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<mpl_::int_<1> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list3<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::stl::insert>, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<1> >, 0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<2> >, 0> > >, 3> > >, 2> > *, std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > > &, std::pair<int, int> &> &, const boost::phoenix::default_actions &> &, boost::proto::envns_::empty_env>::operator()' requested here 
     BOOST_PROTO_TRANSFORM(evaluator) 
     ^
/usr/local/include/boost/proto/transform/impl.hpp:228:9: note: expanded from macro 'BOOST_PROTO_TRANSFORM' 
     BOOST_PROTO_TRANSFORM_(PrimitiveTransform, void)              \ 
     ^
/usr/local/include/boost/proto/transform/impl.hpp:213:16: note: expanded from macro 'BOOST_PROTO_TRANSFORM_' 
     return boost::proto::detail::apply_transform<transform_type(Expr const &, State const &)>()(e, s, d); \ 
      ^
/usr/local/include/boost/phoenix/core/meta_grammar.hpp:139:16: note: in instantiation of function template specialization 'boost::phoenix::evaluator::operator()<const boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::at_c, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<mpl_::int_<1> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list3<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::stl::insert>, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<1> >, 0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<2> >, 0> > >, 3> > >, 2> > &, const boost::phoenix::vector2<boost::phoenix::vector3<const boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::at_c, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<mpl_::int_<1> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list3<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::stl::insert>, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<1> >, 0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<2> >, 0> > >, 3> > >, 2> > *, std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > > &, std::pair<int, int> &> &, const boost::phoenix::default_actions &> &>' requested here 
     return e(expr, ctx); 
      ^
/usr/local/include/boost/phoenix/core/detail/preprocessed/actor_operator_10.hpp:31:385: note: in instantiation of function template specialization 'boost::phoenix::eval<boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::at_c, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<mpl_::int_<1> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list3<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::stl::insert>, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<1> >, 0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<2> >, 0> > >, 3> > >, 2> >, boost::phoenix::vector2<boost::phoenix::vector3<const boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::at_c, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<mpl_::int_<1> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list3<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::stl::insert>, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<1> >, 0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<2> >, 0> > >, 3> > >, 2> > *, std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > > &, std::pair<int, int> &> &, const boost::phoenix::default_actions &> >' requested here 
     template <typename This, typename A0 , typename A1> struct result<This(A0 & , A1 &)> : result_of::actor<proto_base_expr, A0 & , A1 &> {}; template <typename A0 , typename A1> typename result_of::actor<proto_base_expr, A0 & , A1 &>::type operator()(A0 & a0 , A1 & a1) const { typedef vector3< const actor<Expr> *, A0 & , A1 & > env_type; env_type env = {this, a0 , a1}; return phoenix::eval(*this, phoenix::context(env, default_actions())); } template <typename A0 , typename A1> typename result_of::actor<proto_base_expr, A0 & , A1 &>::type operator()(A0 & a0 , A1 & a1) { typedef vector3< const actor<Expr> *, A0 & , A1 & > env_type; env_type env = {this, a0 , a1}; return phoenix::eval(*this, phoenix::context(env, default_actions())); } template <typename This, typename A0 , typename A1> struct result<This(A0 & , A1 const&)> : result_of::actor<proto_base_expr, A0 & , A1 const&> {}; template <typename A0 , typename A1> typename result_of::actor<proto_base_expr, A0 & , A1 const&>::type operator()(A0 & a0 , A1 const& a1) const { typedef vector3< const actor<Expr> *, A0 & , A1 const& > env_type; env_type env = {this, a0 , a1}; return phoenix::eval(*this, phoenix::context(env, default_actions())); } template <typename A0 , typename A1> typename result_of::actor<proto_base_expr, A0 & , A1 const&>::type operator()(A0 & a0 , A1 const& a1) { typedef vector3< const actor<Expr> *, A0 & , A1 const& > env_type; env_type env = {this, a0 , a1}; return phoenix::eval(*this, phoenix::context(env, default_actions())); } template <typename This, typename A0 , typename A1> struct result<This(A0 const& , A1 &)> : result_of::actor<proto_base_expr, A0 const& , A1 &> {}; template <typename A0 , typename A1> typename result_of::actor<proto_base_expr, A0 const& , A1 &>::type operator()(A0 const& a0 , A1 & a1) const { typedef vector3< const actor<Expr> *, A0 const& , A1 & > env_type; env_type env = {this, a0 , a1}; return phoenix::eval(*this, phoenix::context(env, default_actions())); } template <typename A0 , typename A1> typename result_of::actor<proto_base_expr, A0 const& , A1 &>::type operator()(A0 const& a0 , A1 & a1) { typedef vector3< const actor<Expr> *, A0 const& , A1 & > env_type; env_type env = {this, a0 , a1}; return phoenix::eval(*this, phoenix::context(env, default_actions())); } template <typename This, typename A0 , typename A1> struct result<This(A0 const& , A1 const&)> : result_of::actor<proto_base_expr, A0 const& , A1 const&> {}; template <typename A0 , typename A1> typename result_of::actor<proto_base_expr, A0 const& , A1 const&>::type operator()(A0 const& a0 , A1 const& a1) const { typedef vector3< const actor<Expr> *, A0 const& , A1 const& > env_type; env_type env = {this, a0 , a1}; return phoenix::eval(*this, phoenix::context(env, default_actions())); } template <typename A0 , typename A1> typename result_of::actor<proto_base_expr, A0 const& , A1 const&>::type operator()(A0 const& a0 , A1 const& a1) { typedef vector3< const actor<Expr> *, A0 const& , A1 const& > env_type; env_type env = {this, a0 , a1}; return phoenix::eval(*this, phoenix::context(env, default_actions())); } 
                                                                                                   ^
source.cpp:16:44: note: in instantiation of function template specialization 'boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::at_c, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<mpl_::int_<1> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list3<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::stl::insert>, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<1> >, 0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<2> >, 0> > >, 3> > >, 2> >::operator()<std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >, std::pair<int, int> >' requested here 
    if (phx::at_c<1>(phx::insert(arg1, arg2))(map, value)) 
             ^
1 error generated. 

我即将用尽想法如何正确评估插入的结果。任何帮助,将不胜感激。

编辑: 我的问题的更广泛的背景是,我试图解析一个C++像使用boost :: spirit :: qi枚举。我发现任何试图实现相同的示例都不检查重复的枚举成员。这里有一个代码片断与两个相关的规则:

enumerationMember = identifier[at_c<0>(_val) = _1] > 
    // If there is an explicit value defined use it. 
    ((lit('=') > int_[at_c<1>(_val) = _1]) | 
    // Otherwise use the value of argument _r1 instead. 
    eps[at_c<1>(_val) = _r1]); 
    enumeration = lit("enum") > typeName[at_c<0>(_val) = _1] > lit(':') > 
    enumerationType[at_c<1>(_val) = _1] > braceOpen > 
    // Initialize _a with 0. 
    eps[_a = 0] > 
    // Zero or one comma separated list of members. 
    -(enumerationMember(_a)[//_pass = boost::phoenix::at_c<1>(<- I'm looking for something like this.. 
     insert(at_c<2>(_val), _1)] 
     // Set _a to the value of the last member + 1. 
     [_a = at_c<1>(_1) + 1] 
     % lit(',')) > 
    braceClose; 
+0

我相信你应该使用boost :: fusion :: at_c。像[this](http://liveworkspace.org/code/4C8nzP$4)。 – 2013-02-16 14:50:37

+0

我不认为这是一个选项,因为它不是我调用actor对象,而是一些boost :: spirit :: qi解析器规则。我会将这个背景添加到我的问题中。 – Stacker 2013-02-16 14:54:42

+1

对,你可以像[this]一样使用它(http://liveworkspace.org/code/4C8nzP$5)。唯一的变化是圆括号中的括号。在语义动作中,最后不需要'()'。 – 2013-02-16 15:49:01

回答

2

基于@llonesmiz的意见,我找到了一种解决方法。核心问题似乎是在整个嵌套操作中不能正确传递参数(或者我正在做一些与boost :: phoenix根本错误的操作):

phx :: at_c < 1>(phx :: insert(arg1 ,arg2))(map,value)

其中at_c返回的操作应将两个参数map和value转发给insert返回的操作。

与此相反,以下不工作:

PHX :: at_c < 1>(PHX ::插入件(ARG1,ARG2)(地图,值))()

然而,升压内:: spirit :: qi解析器我没有直接访问映射,因为它是我的返回值之一,我需要懒惰评估(无论如何,这是boost :: phoenix的全部观点)。因此,它似乎并不直接适用于本(简化)语法分析器规则:

enumeration = lit("enum") > typeName[at_c<0>(_val) = _1] > braceOpen > 
    // Initialize _a with 0. 
    eps[_a = 0] > 
    // Zero or one comma separated lists of members. 
    -(enumerationMember(_a) 
     // Only pass if the new member is unique. 
     [_pass = at_c<1>(insert(at_c<2>(_val), _1))] // <- Error 
     // Set _a to the value of the last member + 1. 
     [_a = at_c<1>(_1) + 1] 
     % lit(',')) > 
    braceClose; 

我找到的解决方法是使用两个语义动作和插入的结果暂时存储到一个局部变量:

现在被命名为 enumeration规则的
enumeration = lit("enum") > typeName[at_c<0>(_val) = _1] > braceOpen > 
    // Initialize _a with 0. 
    eps[_a = 0] > 
    // Zero or one comma separated lists of members. 
    -(enumerationMember(_a) 
     // Temporarily store the result of insert into the local variable _b. 
     [_b = insert(at_c<2>(_val), _1)] 
     // Only pass if the previous insert was successful. 
     [_pass = at_c<1>(_b)] 
     // Set _a to the value of the last member + 1. 
     [_a = at_c<1>(_1) + 1] 
     % lit(',')) > 
    braceClose; 

定义是这样的:

boost::spirit::qi::rule<Iterator, Enumeration(), 
    boost::spirit::qi::locals< 
    int, // _a 
    std::pair<std::map<std::string, int>::iterator, bool> // _b 
    >, space_type> enumeration; 

我想没有比使用本地存储的RESU一些更优雅的方式插入的。因此,我现在将继续讨论这个问题,以便提供更优雅的答案。

+0

对不起,我提出这些意见时并没有完全理解你的问题。现在我看到了你的问题,恐怕我不知道如何解决它。希望有人知道更多会帮助。为了“有趣”,我实现了一个不使用凤凰的枚举解析器。你可以在这里看到它(http://liveworkspace.org/code/3KfI0r$5)(如果你在最后修改了最后的循环,它应该可以在不需要C++ 11的情况下编译)。 – 2013-02-16 19:27:06

+0

您的意见仍然有帮助,谢谢:)看看你的方法,我不确定将逻辑放入AST结构还是尽可能地更好地保留解析器规则是一个很好的决定。这两种方法我都看到了几个优点和缺点。那么,我需要更多的经验与boost :: spirit&co,现在我仍然处于“实验阶段”:) – Stacker 2013-02-16 20:10:53

+0

看看你是否喜欢[这个版本](http://liveworkspace.org/code/ 3KfI0r $ 7)更多。 – 2013-02-16 20:29:38