LINUX.ORG.RU

[C++, boost::spirit::phoenix, std::get] Обернуть std::get в phoenix-овскую function


0

1

Доброго всем времени суток. Случилась такая проблема: при попытке завернуть std::get в функциональный объект boost::spirit::phoenix вываливается здоровенный листинг ошибок на предмет того (как я смог понять), что такую сигнатуру использовать не получится. Как можно заставить собираться нижеприведённый код, и можно ли это сделать вообще?

#include <tuple>
#include <vector>
#include <string>
#include <iostream>
//--------------------------------------------------------------------------
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
//--------------------------------------------------------------------------
/*
  g++ -Wall -std=gnu++0x -o ./main ./main.cpp
*/
//--------------------------------------------------------------------------
namespace qi = boost::spirit::qi;
namespace ph = boost::phoenix;
//--------------------------------------------------------------------------
typedef std::tuple<int,int,float> TpPointsTuple;
typedef std::vector<TpPointsTuple> TpPointsTempStorage;
//--------------------------------------------------------------------------
struct phoenix_get_impl
{
  template <std::size_t I,typename... Args>
  struct result
  {
    typedef typename std::tuple_element<I,std::tuple<Args...>>::type type;
  };
  template <std::size_t I,typename... Args>
  typename result<I,Args...>::type& operator () (std::tuple<Args...>& t)
  {
    return std::get<I> (t);
  }
};
ph::function<phoenix_get_impl> const phoenix_get = phoenix_get_impl();
//--------------------------------------------------------------------------
struct phoenix_make_tuple_impl
{
  template <typename... Args>
  struct result
  {
    typedef std::tuple<Args...> type;
  };
  template <typename... Args>
  typename result<Args...>::type operator () (Args... args) const
  {
    return std::make_tuple(args...);
  }
};
ph::function<phoenix_make_tuple_impl> const phoenix_make_tuple = phoenix_make_tuple_impl();
//--------------------------------------------------------------------------
template <typename Iterator>                    \
struct TpPointsParser : qi::grammar             \
<Iterator,TpPointsTempStorage(),qi::space_type> \
{
  TpPointsParser(void) : TpPointsParser::base_type(start)
  {
    int_strong %= qi::int_ >> !(qi::punct >> *qi::digit);
    sectionName = qi::alpha >> *qi::alnum >> qi::lit('=');
    requiredData = (int_strong >> int_strong >> -qi::float_)  \
      [phoenix_make_tuple(qi::_1,qi::_2,qi::_3)];
    start = sectionName >> requiredData         \
      //[ph::push_back(qi::_val,qi::_1)];
      [std::cerr << phoenix_get.operator () <0> (qi::_1)];
    return;
  }
  qi::rule<Iterator,int()> int_strong;
  qi::rule<Iterator,void(),qi::space_type> sectionName;
  qi::rule<Iterator,TpPointsTuple(),qi::space_type> requiredData;
  qi::rule<Iterator,TpPointsTempStorage(),qi::space_type> start;
};

//--------------------------------------------------------------------------
int main(int argc,char** argv)
{
//#define USE_IT
#ifdef USE_IT
  std::tuple<int,int> t(100500,9000);
  phoenix_get_impl pgi;
  std::cerr << pgi.operator () <0> (t) << std::endl;
#else
  std::string data("point0 = 9000 100500\n");
  std::string::const_iterator walker = data.begin();
  std::string::const_iterator end = data.end();
  bool result = true;
  TpPointsTempStorage tpPointsTempStorage;
  TpPointsParser<std::string::const_iterator> tpPointsParser;
  while((walker != end) && (result == true))
  {
    result = qi::phrase_parse(walker,end,tpPointsParser,qi::space,tpPointsTempStorage);
    std::cerr << std::endl;
  }
  std::cerr << "tpPointsTempStorage.size() = " \
            << tpPointsTempStorage.size()      \
            << std::endl;
#endif//USE_IT
  return 0;
}

enjoy your C++ w/templates

Только потому, что на темплейтах можно писать такое совсем не значит, что это нужно делать.

Возми нормальные генераторы парсеров с вменяемым описанием грамматики и на парь мозги себе и остальным.

anonymous ()

Жесть... Вообще заворачивать в феникс, а потом доставать обратно operator() - выглядит противоестественно, это уже не ленивая вункция выйдет. На работу через полтора часа дойду и гляну.

ratatosk ()
Ответ на: enjoy your C++ w/templates от anonymous

нормальные генераторы парсеров с вменяемым описанием грамматики

И что из нормальных генераторов парсеров, написанных на C++, ты можешь предложить? А прибивать гвоздями plain C к C++ — то ещё удовольствие.

one_more_hokum ★★★ ()
Ответ на: комментарий от ratatosk

нельзя там нормальную с++11 лямбду заюзать?

Не получится, конпелятор — GCC 4.4.0.

one_more_hokum ★★★ ()
Ответ на: комментарий от ratatosk

Вообще заворачивать в феникс, а потом доставать обратно operator() - выглядит противоестественно

Отчего же? В документации прямо так и описано было. Или это Хартмут кому-то пример давал, не помню уже...

one_more_hokum ★★★ ()
Ответ на: комментарий от slackwarrior

обновить конпелятор?

Если бы я один работал над проектом — да без проблем.

one_more_hokum ★★★ ()
Ответ на: комментарий от one_more_hokum

ммм... обсудить со стаей товарищей обновление конпелятора?

slackwarrior ★★★★★ ()
Ответ на: комментарий от slackwarrior

обсудить... обновление конпелятора?

На ближайшее время невозможно. Хотелось бы узнать, решаема-ли проблема с этим std::get в принципе на GCC 4.4.0, или не? Если да, то как.

one_more_hokum ★★★ ()
Ответ на: комментарий от one_more_hokum

А можешь найти, где это было? Выглфдит странно - всё-таки одно дело у тебя функциональный объект, завернутый в фениксовские типы, другое дело - функция-член. Не представляю, как второе може быть ленивым вызывом. Или это надо какой-нибудь bind туда вставлять.

p.s. Вчера на работе внезапно надо было работать, потом потыкался, так и не получилось, пардон.

p.p.s. Испытал неиллюзорную злость, глядя на бесполезный высер gcc. Clang и вовсе сдох при попытке компильнуть. Даже захотелось сказать что-то плохое про плюсы...

ratatosk ()
Ответ на: комментарий от ratatosk

А можешь найти, где это было?

Что нашлось/вспомнилось быстрее всех.

Испытал неиллюзорную злость, глядя на бесполезный высер gcc

Не то, чтобы он бесполезный... Spirit-то, по факту, реализует ещё один компилятор поверх GCC, и ошмётки его работы вываливаются в виде этих километровых листингов ошибок. Кое-чего уже становится понятно, но сильно не всё.

Clang и вовсе сдох при попытке компильнуть

Он ишшо ма-аленький, ему позволительно.

На сей момент задачу я упростил до того, чтобы в semantic action попытаться доступиться до элементов (к примеру) std::tuple, переданного туда, как какой-нить параметр (qi::_1).

one_more_hokum ★★★ ()
Ответ на: комментарий от one_more_hokum

Что нашлось/вспомнилось быстрее всех.

Там везде сам объект используется, его оператор() уже сам феникс извлекает когда нужно.

ratatosk ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.