c++ - 对 boost Spirit/phoenix/C++11 交互感到困惑

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

我已尽力减少这个问题。

如果我取消注释voidinitialize(),则此代码将编译。如果我将其注释掉,那么它就不会构建。

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

我尝试过在 OS X Lion(带有 libc++)上使用stock clang 编译器以及在 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 的编译器输出非常冗长,因此我将其作为要点包含在内:

代码如下...

#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会知道如何将成员函数绑定(bind)到它。


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

  • 一路走来,std::vector<> 的存在在成员函数指针的 type 中,ADL 搜索 std 命名空间并找到 std::bind ,而不是 phoenix::bind
  • 不知何故,当你经过val时,而不是 *val ,编译器选择phoenix bind作为更好的匹配。
  • 您可以看到,当您有一个成员函数时,例如, int (而不是 std 命名空间中的类型),问题消失了,并且始终选择 phoenix bind。

您可以通过检查 this minimal test program 的输出来看到上述观察结果 转储各种绑定(bind)表达式的 typeid(并通过 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)];
}

关于c++ - 对 boost Spirit/phoenix/C++11 交互感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15326235/

相关文章:

c++ - 使用专门的可变参数模板类的声明

c++ - 为什么 C++ 中没有对所有 C++ 标准库类型特征的语言支持?

c++ - C++11/C++14 中的文字类型类

c++ - 如何使用着色器制作复古/ NEON /发光效果?

c++ - 传入字符串和整数的字符串函数

c# - 在 Visual Studio 解决方案中结合 C# 和 C++

python - 如何使用 Boost.Python 在 Python 中调用内置函数

c++ - C++ 中的 ARM Cortex-M 中断处理程序

c++ - 指向结构的指针的运算符重载

android - 在 Android Studio 中为 NDK 项目构建符号花费的时间太长