2

私はできる限りこの問題を軽減しようとしました。

コメントを外すvoid initialize()と、このコードはコンパイルされます。コメントアウトしたままにしておくと、ビルドされません。

この問題を解決するために私が見つけた唯一の方法は、C++03 モードでビルドすることboost::shared_ptrですstd::shared_ptr

OS X Lion (libc++ を使用) では標準の 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)];
}
4

1 に答える 1

2
#define BOOST_SPIRIT_USE_PHOENIX_V3

私のためにそれを修正します。そして、フェニックスがメンバー関数をそれにバインドする方法を知っているという理由*valだけでに変更します。val


更新@llonesmizが示唆したように、これは確かにADLに関連していることがわかりました。関係は非常に微妙ですが。

  • 途中のどこかで、member-function-pointerstd::vector<>に存在することで、ADLはstd名前空間を検索しstd::bind、の代わりにを検索しますphoenix::bind
  • どういうわけか、を渡すときval、代わりに*val、コンパイラはフェニックスbindをより良い一致として選択します。
  • intたとえば、 (名前空間の型ではなくstd)を受け取るメンバー関数がある場合、問題は解消され、フェニックスバインドが常に選択されていることがわかります。

さまざまなバインド式の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)];
}
于 2013-03-10T19:08:17.383 に答える