我想決議string | (string, int)并將其存盤在一個結構中,該結構將int組件默認為某個值。 X3中這種結構的屬性是variant<string, tuple<string, int>>。 我在想,我可以有一個結構,它需要一個字串或者一個(string, int)來自動被填充:
struct bar
{
bar (std::string x = "", int y = 0) : baz1 {x}, baz2 {y} {}。
std::string baz1;
int baz2;
};
BOOST_FUSION_ADAPT_STRUCT (disj::ast::bar, baz1, baz2)
然后簡單地有:
const x3:: rule<class bar, ast::bar> bar = "bar"/span>;
使用 x3::int_。
using x3::ascii::alnum;
auto const bar_def = ( (alnum) | (' (' >> (alnum) > > ',' >> int_ >> ')')) >> '; '。
BOOST_SPIRIT_DEFINE(bar)。
然而這并不奏效:
/usr/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:139:59。error。靜態斷言失敗。期待一個單一元素的融合序列
139 | static_assert(traits::has_size<Attribute, 1>:value,
將baz2設定為optional并沒有幫助。 解決這個問題的一個方法是有一個variant欄位或從該型別繼承:
struct string_int {
std::string s;
int i;
};
結構foo {
boost::variant<std::string, string_int> var;
};
BOOST_FUSION_ADAPT_STRUCT (disj::astr:string_int, s, i)
BOOST_FUSION_ADAPT_STRUCT (disj::ast::foo, var)
(由于某些原因,我必須使用boost::variant而不是x3::variant來使operator<<作業;另外,使用std::pair或tuple來使string_int不作業,但boost::fusion::deque可以。) 然后,我們可以通過某種方式裝備foo來獲得字串和整數。
問題:在 X3 中正確的、干凈的方法是什么? 有沒有比第二種方法和給foo配備訪問器更自然的方法呢?
uj5u.com熱心網友回復:
遺憾的是,X3部分中的措辭極其稀疏,并且允許它(對比Qi部分)。
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;
模板 <typename Expr>
std::string inspect(Expr const& expr) {
using A = typename x3::traits::attributee_of<Expr, x3::unused_type> ::type;
return boost::core::demangle(typeid(A).name() )。
}
int main()
{
std::cout << inspect(x3::double_ | x3::int_) << "
"; // variant expected
std::cout << inspect(x3::int_ | "bla" >> x3::int_) << "
"; // variant "understandable".
std::cout << inspect(x3::int_ | x3::int_) << "
"; // variant suprising:.
}
印刷品
boost::variant<double, int>
boost::variant<int, int>
boost::variant<int, int>
所有的希望并沒有消失
在你的具體案例中,你可以欺騙系統:auto const bar_def = //
( x3::alnum >> x3::attr(-1) /
| '(' >> x3::alnum >> ',' >> x3::int_ >> ')' /
) >> ';'。
注意我們如何為第一個分支 "注入 "一個int值。這滿足了屬性傳播之神的要求:
Live On Coliru#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/fusion/include/io.hpp>/span>
#include <iomanip>/span>
namespace x3 = boost::spirit::x3;
namespace disj::ast {
struct bar {
std::string x;
int y;
};
using boost::fusion::operator<< 。
} //namespace disj::ast
BOOST_FUSION_ADAPT_STRUCT(disj::ast::bar, x, y)
namespace disj::parser {
const x3::rule<class bar, ast::bar> bar = "bar"/span>;
auto const bar_def = /
( x3::alnum >> x3::attr(-1) //
| '(' >> x3::alnum >> ',' >> x3::int_ >> ') ' /
)>> ';'。
BOOST_SPIRIT_DEFINE(bar)
}
namespace disj {
void run_tests() {
for(std::string const input : {
""/span>,
";"。
"bla;"。
"bla, 42;"。
"(bla, 42);"。
}) {
ast::bar val;
auto f = begin(input), l = end(input)。
std::cout << "
" << quoted(input) << " -> "。
if (phrase_parse(f, l, parser::bar, x3::space, val) {
std::cout << "Parsed: " << val < < "
"。
} else {
std::cout << "Failed
"。
}
if (f! =l) {
std::cout << " -- Remaining " << quoted(std::string_view(f, l) << "
"。
}
}
}
}
int main()
{
disj::run_tests()。
}
Prints
"" -> Failed
";" -> 失敗
-- 剩余";"
"bla;" ->決議了。(bla -1)
"bla, 42;" -> 故障
--剩余的 "bla, 42;"
"(bla, 42);" ->決議了。(bla 42)
1只是今天
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/331850.html
標籤:
