[英]How to tel a boost::karma::rule not to consume its attribute without providing a valid generator?
假設我們有以下源代碼:
#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
的屬性的生成器。
我看到幾種解決方法:
karma::unused_type
std::nullptr_t
替換為karma::unused_type
:它適用於此示例,但可能在更復雜的語法中引入歧義。 karma::unused_type
屬性的中間規則 。 快速修復有效但沒有意義。 問題 :我如何告訴karma::rule
生成簡單文字,而不關心是否為其屬性生成器?
您似乎偶然發現了臭名昭著的單元素融合序列難題[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;
}
但是,這根本沒有任何意義,因為文檔指出:
像
string
一樣,lit
也發出一串字符。 主要的區別是,lit
不消耗[原文]的屬性 。 像一個普通字符串"hello"
或std::basic_string
是相當於一個lit
因此,我只是...一時興起,通過使用與Qi端單元素融合序列相同的變通方法,使事情變得有些強迫:
query = karma::eps << "yeah";
而且, voilà : 可行 : Live on Coliru
[1]見
等等,這是一個可悲的缺陷,對於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;
};
我仍然對任何評論,責備或其他解決方案感興趣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.