迷惑精神/凤凰/ C ++ 11互动困惑

时间:2013-03-10 19:01:51

标签: c++ boost c++11 boost-spirit boost-phoenix

我尽力减少这个问题。

如果我取消注释void initialize(),则此代码会编译。如果我把它留下来注释掉,那就不会构建。

我找到解决此问题的唯一方法是使用boost::shared_ptr而不是std::shared_ptr构建C ++ 03模式。

我尝试使用OS X Lion上的stock clang编译器(使用libc ++)和CentOS 6.4 x64上的以下编译器:

/opt/llvm/3.2/bin/clang++ -gcc-toolchain /opt/gcc/4.7.2 -std=gnu++11 foo.cc -I/opt/boost/1.53.0/include -DBOOST_SPIRIT_USE_PHOENIX_V3 -DBOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT -DBOOST_SPIRIT_DEBUG
/opt/llvm/3.1/bin/clang++ -gcc-toolchain /opt/gcc/4.7.2 -std=gnu++11 foo.cc -I/opt/boost/1.53.0/include -DBOOST_SPIRIT_USE_PHOENIX_V3 -DBOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT -DBOOST_SPIRIT_DEBUG
/opt/llvm/3.0/bin/clang++ -gcc-toolchain /opt/gcc/4.7.2 -std=gnu++11 foo.cc -I/opt/boost/1.53.0/include -DBOOST_SPIRIT_USE_PHOENIX_V3 -DBOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT -DBOOST_SPIRIT_DEBUG
/opt/gcc/4.7.2/bin/g++ -std=gnu++11 foo.cc -I/opt/boost/1.53.0/include -DBOOST_SPIRIT_USE_PHOENIX_V3 -DBOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT -DBOOST_SPIRIT_DEBUG
/opt/gcc/4.7.1/bin/g++ -std=gnu++11 foo.cc -I/opt/boost/1.53.0/include -DBOOST_SPIRIT_USE_PHOENIX_V3 -DBOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT -DBOOST_SPIRIT_DEBUG

像往常一样,精神的编译器输出非常冗长,所以我把它作为一个要点包含在内:

守则遵循......

#include <boost/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <memory>

class Object {
    public:
        void initialize(std::vector<int>) {
        }

        //void initialize() {
        //}
};

int main() {
    boost::spirit::qi::rule<std::string::iterator, int()> integer;
    boost::spirit::qi::rule<std::string::iterator, std::shared_ptr<Object>()> object;

    using boost::phoenix::bind;
    using boost::spirit::_val;
    using boost::spirit::_1;

    object  
        = (*integer) [bind(&Object::initialize, *_val, _1)];
}

1 个答案:

答案 0 :(得分:2)

#define BOOST_SPIRIT_USE_PHOENIX_V3

为我修复它。并将*val更改为val因为phoenix将知道如何将成员函数绑定到它。


更新正如@llonesmiz暗示的那样,事实证明这与ADL有关。虽然这种关系非常微妙。

  • 在此过程中,成员函数指针的类型std::vector<>的存在使得ADL搜索std命名空间并找到std::bind,而不是phoenix::bind
  • 不知何故,当你传递val而不是*val时,编译器会选择凤凰bind作为更好的匹配。
  • 你可以看到,如果你有一个成员函数,比如int(而不是std命名空间中的类型),问题就会消失,并且总是选择phoenix bind。

您可以通过检查转储各种绑定表达式的类型ID的 this minimal test program 的输出来查看上述观察结果(并通过c++filt运行它们)



#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/phoenix.hpp>
#include <memory>

class Object {
    public:
        void initialize(std::vector<int>) {
        }
};

int main() {
    boost::spirit::qi::rule<std::string::iterator, int()> integer;
    boost::spirit::qi::rule<std::string::iterator, std::shared_ptr<Object>()> object;

    using boost::phoenix::bind;
    using boost::spirit::_val;
    using boost::spirit::_1;

    object  
        = (*integer) [bind(&Object::initialize, _val, _1)];
}