解析器表达式生成的属性类型为quite well-documented。但这可能会让人迷失方向且耗时。
这里有个技巧:发送一个哨兵来检测属性类型:
struct Sniffer
{
typedef void result_type;
template <typename T>
void operator()(T const&) const { std::cout << typeid(T).name() << "\n"; }
};
然后使用后面的解析器表达式
(input >> (qi::repeat(0,2)[qi::char_(';') >> input])) [ Sniffer() ]
将转储:
N5boost6fusion7vector2ISt6vectorIsSaIsEES2_INS1_IcS4_EESaIS5_EEEE
c++filt -1 会告诉你代表:
boost::fusion::vector2<
std::vector<short, std::allocator<short> >,
std::vector<boost::fusion::vector2<char, std::vector<short, std::allocator<short> > >,
std::allocator<boost::fusion::vector2<char, std::vector<short, std::allocator<short> > >
> >
>
在 Coliru 上现场观看:http://coliru.stacked-crooked.com/view?id=3e767990571f8d0917aae745bccfa520-5c1d29aa57205c65cfb2587775d52d22
boost::fusion::vector2<std::vector<short, std::allocator<short> >, std::vector<std::vector<short, std::allocator<short> >, std::allocator<std::vector<short, std::allocator<short> > > > >
它可能如此复杂,部分原因是char_(";") 可能是';'(或更明确地说是lit(';'))。 Constrast with this (Coliru):
boost::fusion::vector2<
std::vector<short, ... >,
std::vector<std::vector<short, std::allocator<short> >, ... > >
这应该可以回答您的问题。
旁注:解析事物
不要低估 Spirit 中的自动属性传播。通常,您不必为 exact 公开的属性类型而烦恼。相反,依靠 Spirit 使用的(许多)属性转换将它们分配给您提供的属性引用。
我相信您在精神上了解列表操作员 (%)?我会告诉你如何使用它,不用多说:
vector<vector<short>> data;
qi::parse(f, l, qi::short_ % ',' % ';', data);
现在,如果您需要强制它可能是 1-3 个元素,您可以使用带有 Phoenix 操作的 eps 来声明最大大小:
const string x = "1,2,3;2,3,4;3,4,5";
auto f(begin(x)), l(end(x));
if (qi::parse(f, l,
(qi::eps(phx::size(qi::_val) < 2) > (qi::short_ % ',')) % ';'
, data))
{
cout << karma::format(karma::short_ % ',' % ';', data) << "\n";
}
cout << "remaining unparsed: '" << std::string(f,l) << "'\n";
打印:
1,2,3;2,3,4
remaining unparsed: ';3,4,5'