Как сказать boost::karma::rule, чтобы не использовать его атрибут без предоставления корректного генератора?
Скажем, у нас есть следующий исходный код:
#include <iostream>
#include <string>
#include <iterator>
#include <boost/spirit/include/karma.hpp>
namespace karma = boost::spirit::karma;
template <typename OutputIterator> struct grammar : karma::grammar<OutputIterator, std::nullptr_t()> {
grammar() : grammar::base_type(query) {
query = "yeah";
}
karma::rule<OutputIterator, std::nullptr_t()> query;
};
int main(void) {
typedef std::back_insert_iterator<std::string> iterator_type;
std::string generated;
iterator_type output_it(generated);
//keys_and_values<sink_type> g;
grammar<iterator_type> g;
bool result = karma::generate(output_it, g, nullptr);
std::cout << result << ":" << generated << std::endl;
return 0;
}
Это не в состоянии скомпилировать, потому что karma
не хватает некоторых черт для std::nullptr_t
(это boost::spirit::traits::extract_c_string
а также boost::spirit::traits::char traits
). Точнее говоря, это не удается, потому что karma
не может найти генератор для атрибута типа std::nullptr_t
,
Я вижу несколько способов справиться с этим:
- замещать
std::nullptr_t
отkarma::unused_type
в определении грамматики: он работает на этом примере, но может внести двусмысленность в более сложную грамматику. - Определение специализации черт: На мой взгляд, это грязно и не является общим. Кроме того, это раскрывает мою специализацию стандартного типа для всех, что ведет к потенциальным конфликтам.
- Специализация преобразования атрибута: та же проблема специализации стандартного типа только для меня.
- Написать собственный генератор: лучший кандидат на данный момент, но он серьезно загружает высокотемпературные строки кода по сравнению со сложностью задачи.
- Поместите промежуточное правило с
karma::unused_type
атрибут Быстрое исправление, которое работает, но не имеет смысла.
Вопрос: Как я могу сказать karma::rule
генерировать простой литерал и не заботиться о наличии или отсутствии генератора для его атрибута?
2 ответа
Вы, кажется, наткнулись на обратную сторону печально известной головоломки одноэлементной последовательности слияния [1]:(
Я заметил, потому что ошибка исходит из кода, пытающегося проверить, соответствует ли входная строка атрибуту (lit.hpp):
// fail if attribute isn't matched by immediate literal
typedef typename attribute<Context>::type attribute_type;
typedef typename spirit::result_of::extract_from<attribute_type, Attribute>::type
extracted_string_type;
using spirit::traits::get_c_string;
if (!detail::string_compare(
get_c_string(
traits::extract_from<attribute_type>(attr, context))
, get_c_string(str_), char_encoding(), Tag()))
{
return false;
}
Однако это не имеет никакого смысла, поскольку в документации указано:
lit
, лайкstring
также испускает строку символов. Основное отличие состоит в том, чтоlit
не потребляет [sic] атрибут. Простая строка как"hello"
илиstd::basic_string
эквивалентноlit
Так что я просто... по своей прихоти думал немного привести в порядок, используя тот же обходной путь, который работает для одноэлементных последовательностей слияния на стороне Ци:
query = karma::eps << "yeah";
И, вуаля: это работает: Live On Coliru
[1] См.
- Как использовать класс только с одним атрибутом в AST с Boost Spirit?
- Проблема распространения атрибута Spirit Qi с однокомпонентной структурой
- Ошибка компилятора при адаптации struct с помощью BOOST_FUSION_ADAPT_STRUCT
- Адаптируйте класс, содержащий строковый член, как синтезированный атрибут
И т. Д. Это печальный недостаток, который, вероятно, нужно будет обойти для SpiritV2.
Возможный ответ: после публикации я нашел решение, которое на данный момент меня устраивает. То есть: ввести промежуточное правило.
template <typename OutputIterator> struct grammar : karma::grammar<OutputIterator, std::nullptr_t()> {
grammar() : grammar::base_type(query) {
query = null_rule;
null_rule = "null";
}
karma::rule<OutputIterator, std::nullptr_t()> query;
karma::rule<OutputIterator, karma::unused_type()> null_rule;
};
Я все еще интересуюсь любым комментарием, упреком или другим решением.