假设我们有以下源代码:
#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
生成一个简单的文字而不关心是否有一个生成器用于其属性?
答案 0 :(得分:3)
你似乎偶然发现臭名昭着的单元素融合序列的反面难题 [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;
}
但是,这完全没有意义,因为 docs 状态:
与lit
一样,
string
也会发出一串字符。主要区别在于lit
不会消耗 [sic] 属性。像"hello"
或std::basic_string
这样的普通字符串相当于lit
所以我只是......通过使用适用于Qi方面的单元素融合序列的相同解决方法,突然想到要稍微强制一点:
query = karma::eps << "yeah";
而且,瞧瞧:它有效: Live On Coliru
[1] 参见
等。这是一个可能需要为SpiritV2解决的可悲缺陷。
答案 1 :(得分:1)
可能的答案:发布后,我找到了一个满足我的解决方案。那就是:引入一个中间规则。
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;
};
我仍然对任何评论,责备或其他解决方案感兴趣。