А поскольку a: A, b: vector -> (a >> b): vector, то я думаю, что (qi :: char_ (L "{") >> * (char_-char_ (L "}")) >> char_ (L "}")) должен быть вектором. Это противоречит результату.
На самом деле это не то, что происходит. Применение модернизированного трюка из Определение типов параметров в семантическом действии Spirit
struct sense_f {
template <typename T> void operator()(T&&) const {
std::cout << boost::core::demangle(typeid(T).name()) << "\n";
}
};
static const boost::phoenix::function<sense_f> sense;
Мы можем напечатать фактический тип атрибута:
ru = (char_(L'{') >> *(char_ - char_(L'}')) >> char_(L'}')) [sense(qi::_0)] % qi::eol;
, который будет печатать Live On Coliru :
boost::fusion::vector<wchar_t, std::vector<wchar_t, std::allocator<wchar_t> >, wchar_t>
Простое решение
При условии, что вам не нужно захватывать {}Вы можете просто сделать их литералами вместо char_
:
ru = (L'{' >> *(char_ - L'}') >> L'}') [sense(qi::_0)] % qi::eol;
, которые будут печатать Live On Coliru :
boost::fusion::vector<std::vector<wchar_t, std::allocator<wchar_t> >&>
Действительно, если вы также заставите его распространять атрибут:
ru %= (L'{' >> *(char_ - L'}') >> L'}') [sense(qi::_0)] % qi::eol;
Программа напечатает:
boost::fusion::vector<std::vector<wchar_t, std::allocator<wchar_t> >&>
boost::fusion::vector<std::vector<wchar_t, std::allocator<wchar_t> >&>
"\"id\":23,\"text\":\"sf
sf\""
"\"id\":23,\"text\":\"sfsf\""
Обратите внимание, что существует совместимость атрибутов между std::vector<wchar_t>
иstd::wstring
, поэтому я использовал последний.
Бонус
Если вы действительно хотите включить {} и любой промежуточный пробел, используйте qi::raw
:
ru %= qi::raw [L'{' >> *(char_ - L'}') >> L'}'] [sense(qi::_0)] % qi::eol;
Теперь он печатает:
boost::fusion::vector<boost::iterator_range<__gnu_cxx::__normal_iterator<wchar_t const*, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > >&>
boost::fusion::vector<boost::iterator_range<__gnu_cxx::__normal_iterator<wchar_t const*, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > >&>
"{\"id\":23,\"text\":\"sf
sf\"}"
"{\"id\":23,\"text\":\"sfsf\"}"
Как вы можете видеть, даже iterator_range<It>
имеет атрибут совместимости с std::wstring
, потому что вход также является последовательностью wchar_t
.
Конечно, отключите действие sense
, если вы не хотите этот вывод.
Полный список
Окончательный результат с использованием подхода qi::raw
:
Live On Coliru
#define BOOST_SPIRIT_UNICODE
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
namespace sw = boost::spirit::standard_wide;
namespace qi = boost::spirit::qi;
using sw::char_;
int main() {
std::wstring s = LR"({"id":23,"text":"sf
sf"}
{"id":23,"text":"sfsf"})";
using Data = std::vector<std::wstring>;
using It = std::wstring::const_iterator;
qi::rule<It, Data(), sw::blank_type> ru
= qi::raw [L'{' >> *(char_ - L'}') >> L'}'] % qi::eol;
Data result;
It f = s.begin(), l = s.end();
if (qi::phrase_parse(f, l, ru, sw::blank, result)) {
for (auto& s : result) {
std::wcout << std::quoted(s) << std::endl;
};
} else {
std::wcout << "Parse failed\n";
}
if (f!=l) {
std::wcout << L"Remaining unparsed: " << std::quoted(std::wstring(f,l)) << std::endl;
}
}