被增强精灵/凤凰/ c++ 11的交互弄糊涂了

Confused by a boost spirit / phoenix / C++11 interaction

本文关键字:交互 弄糊涂 c++ 增强 精灵 凤凰      更新时间:2023-10-16

我已经尽力减少这个问题了。

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

我发现解决这个问题的唯一方法是在c++ 03模式下构建boost::shared_ptr而不是std::shared_ptr

我已经尝试了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

与往常一样,spirit的编译器输出非常冗长,因此我将其作为要点包含:

  • 叮当声3.2
  • GCC 4.7.2

代码跟随…

#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)];
}
#define BOOST_SPIRIT_USE_PHOENIX_V3

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


UPDATE正如@llonesmiz所暗示的,这确实与ADL有关。尽管这种关系非常微妙。

  • 在此过程中,成员函数指针类型std::vector<>的存在使ADL搜索std命名空间并找到std::bind,而不是phoenix::bind
  • 不知何故,当你传递val而不是*val时,编译器选择凤凰bind作为更好的匹配。
  • 你可以看到,当你有一个成员函数,说,int(而不是来自std命名空间的类型),问题消失了,凤凰绑定总是被选中。
通过检查的输出,可以看到上面的观察结果。这个最小的测试程序转储各种绑定表达式的类型(并通过c++filt运行它们)
  • http://liveworkspace.org/code/idDtv$0

  • 更新 Clang似乎只喜欢它与boost::shared_ptr代替:http://liveworkspace.org/code/idDtv$3我只能假设这是由于libc++的差异(?)


#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)];
}