Я хочу, чтобы разобрать что-то вроде следующего:Ошибка компиляции пользовательского контейнера для повышающего духа
1;2
=1200
3;4
5;6
линии могут появляться в любом порядке. Линии, начинающиеся с знака =, могут быть более одного, и только последнее имеет значение; строки, содержащие a; представляют пару значений, которые я хочу сохранить на карте. Чтение ответа на this question Я придумал код, который должен быть достаточно хорошим (извините, но я все еще ноб с Духом) и должен делать то, что я пытаюсь достичь. Вот код:
#define BOOST_SPIRIT_USE_PHOENIX_V3
#define DATAPAIR_PAIR
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/mpl/bool.hpp>
#include <map>
#if !defined(DATAPAIR_PAIR)
#include <vector>
#endif
static const char g_data[] = "1;2\n=1200\n3;4\n5;6\n";
typedef std::string DataTypeFirst;
#if defined(DATAPAIR_PAIR)
typedef std::string DataTypeSecond;
typedef std::pair<DataTypeFirst, DataTypeSecond> DataPair;
typedef std::map<DataTypeFirst, DataTypeSecond> DataMap;
#else
typedef std::vector<DataTypeFirst> DataPair;
typedef std::map<DataTypeFirst, DataTypeFirst> DataMap;
#endif
struct MyContainer {
DataMap data;
double number;
};
namespace boost { namespace spirit { namespace traits {
template<> struct is_container<MyContainer> : boost::mpl::true_ {};
template<>
struct container_value<MyContainer> {
typedef boost::variant<double, DataPair> type;
};
template <>
struct push_back_container<MyContainer, double> {
static bool call (MyContainer& parContainer, double parValue) {
parContainer.number = parValue;
return true;
}
};
template <>
struct push_back_container<MyContainer, DataPair> {
static bool call (MyContainer& parContainer, const DataPair& parValue) {
#if defined(DATAPAIR_PAIR)
parContainer.data[parValue.first] = parValue.second;
#else
parContainer.data[parValue[0]] = parValue[1];
#endif
return true;
}
};
} } }
template <typename Iterator>
struct TestGrammar : boost::spirit::qi::grammar<Iterator, MyContainer()> {
TestGrammar (void);
boost::spirit::qi::rule<Iterator, MyContainer()> start;
boost::spirit::qi::rule<Iterator, DataPair()> data;
boost::spirit::qi::rule<Iterator, double()> num;
};
template <typename Iterator>
TestGrammar<Iterator>::TestGrammar() :
TestGrammar::base_type(start)
{
using boost::spirit::qi::alnum;
using boost::spirit::qi::lit;
using boost::spirit::ascii::char_;;
using boost::spirit::qi::double_;
using boost::spirit::qi::eol;
using boost::spirit::qi::eoi;
start %= *((num | data) >> (eol | eoi));
data = +alnum >> lit(";") >> +alnum;
num = '=' >> double_;
}
int main() {
std::cout << "Parsing data:\n" << g_data << "\n";
TestGrammar<const char*> gramm;
MyContainer result;
boost::spirit::qi::parse(static_cast<const char*>(g_data),
g_data + sizeof(g_data)/sizeof(g_data[0]) - 1,
gramm,
result
);
std::cout << "Parsed data:\n";
std::cout << "Result: " << result.number << "\n";
for (const auto& p : result.data) {
std::cout << p.first << " = " << p.second << '\n';
}
return 0;
}
Я развиваю это на Gentoo Linux, используя Dev-LIBS/повышения-1.55.0-r2: 0/1.55.0 и GCC (Gentoo 4.8.3 P1.1, пирог -0,5,9) 4.8.3. Компиляция выше код я получаю сообщение об ошибке, как
/usr/include/boost/spirit/home/support/container.hpp:278:13: ошибка: «структура MyContainer» не имеет элемента с именем «всунуть»
как обходной путь, я придумал альтернативный код, который вы получите, комментируя строку #define DATAPAIR_PAIR. В этом случае код компилируется и работает, но я действительно хочу пару, где я могу, например, смешивать значения std :: string и int. Почему использование std :: pair в качестве атрибута для моего правила данных заставляет компилятор пропустить правильную специализацию push_back_container? Можно ли исправить код и заставить его работать, используя std :: pair или что-нибудь эквивалентное?
[This] (http://coliru.stacked-crooked.com/a/81459094d3aed670) работает, но далек от хорош. Единственное добавление отмечено «// ADDED». К сожалению, я не знаю, почему это необходимо в вашем случае, а не в примере, связанном или обходном пути. – llonesmiz
@cv_and_he какое время – sehe
@cv_and_he это довольно странное требование (на самом деле это имеет смысл, но это странно в том смысле, что это не всегда требуется). Хорошая работа. Я не мог заставить его работать, поэтому обманул, посмотрев на ваше решение :) – sehe