Смущенный взаимодействием духа повышения / Phoenix / C ++ 11

Я пытался уменьшить эту проблему, насколько я могу.

Если я раскомментирую void initialize(), то этот код компилируется. Если я оставлю его закомментированным, то он не будет построен.

Единственный способ, который я нашел, чтобы решить эту проблему, это собрать в режиме C ++ 03 с boost::shared_ptr вместо std::shared_ptr,

Я попытался с помощью стандартного компилятора clang на OS X Lion (с 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 довольно многословен, поэтому я включил его в виде сущности:

Кодекс следует …

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

2

Решение

#define BOOST_SPIRIT_USE_PHOENIX_V3

Исправляет это для меня. И изменить *val чтобы просто val потому что Феникс будет знать, как привязать функцию-член к нему.


ОБНОВИТЬ Как намекнул @llonesmiz, оказывается, что это действительно связано с ADL. Хотя отношение очень тонкое.

  • Где-то по пути, присутствие std::vector<> в тип указатель на член-функцию заставляет ADL искать пространство имен std и находить std::bind, вместо phoenix::bind,
  • Как-то, когда вы проходите val, вместо *valКомпилятор выбирает феникса bind как лучший матч.
  • Вы можете видеть, что когда у вас есть функция-член, которая принимает, скажем, int (вместо типа из std namespace), проблема исчезает, и привязка Phoenix всегда выбирается.

Вы можете увидеть вышеприведенные наблюдения, проверив вывод эта минимальная тестовая программа который сбрасывает 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)];
}
2

Другие решения

Других решений пока нет …