簡體   English   中英

如何打電話給boost :: karma :: rule在不提供有效生成器的情況下不要消耗其屬性?

[英]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_stringboost::spirit::traits::char traits )。 更具體地說,它失敗是因為karma無法找到類型為std::nullptr_t的屬性的生成器。

我看到幾種解決方法:

  1. 在語法定義karma::unused_type std::nullptr_t替換為karma::unused_type :它適用於此示例,但可能在更復雜的語法中引入歧義。
  2. 定義特質特化 :我認為這是骯臟的,不是通用的。 另外,它向所有人公開了我對標准類型的專業化,從而導致潛在的沖突。
  3. 專門化屬性轉換 :專門為我專門化標准類型的問題。
  4. 編寫一個自定義生成器 :到目前為止最好的選擇,但是與任務復雜性相比,它會占用大量的高度模板化的代碼行。
  5. 設置帶有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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM