我正在学习 boost::spirit
,我正在尝试读取一些文本并将其解析为一个结构体。
例如,"2: 4.6"
在下面的 2
中被解析为 int 4.6
和 double TestStruct
:
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace qi = boost::spirit::qi;
struct TestStruct {
int myint;
double mydouble;
TestStruct() {}
TestStruct(std::pair<int,double> p) : myint(p.first), mydouble(p.second) {}
};
template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, TestStruct(), Skipper> {
MyGrammar() : MyGrammar::base_type(mystruct) {
mystruct0 = qi::int_ >> ":" >> qi::double_;
mystruct = mystruct0;
}
qi::rule<Iterator, std::pair<int,double>(), Skipper> mystruct0;
qi::rule<Iterator, TestStruct(), Skipper> mystruct;
};
int main() {
typedef boost::spirit::istream_iterator It;
std::cin.unsetf(std::ios::skipws);
It it(std::cin), end; // input example: "2: 3.4"
MyGrammar<It, qi::space_type> gr;
TestStruct ts;
if (qi::phrase_parse(it, end, gr, qi::space, ts) && it == end)
std::cout << ts.myint << ", " << ts.mydouble << std::endl;
return 0;
}
它工作得很好,但我想知道如何简化这段代码?
例如,我想摆脱
mystruct0
语法规则,该规则仅用于标记类型 std::pair<int,double>
,然后用于根据 TestStruct
规则自动构造 mystruct
对象。如果可能,我还希望能够从
TestStruct
中删除 std::pair
构造函数。那么,可以以某种方式编译以下代码吗?那将是一个更好的解决方案:
struct TestStruct {
int myint;
double mydouble;
TestStruct() {}
TestStruct(int i, double d) : myint(i), mydouble(d) {}
};
template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, TestStruct(), Skipper> {
MyGrammar() : MyGrammar::base_type(mystruct) {
mystruct = qi::int_ >> ":" >> qi::double_;
}
qi::rule<Iterator, TestStruct(), Skipper> mystruct;
};
int main() {
typedef boost::spirit::istream_iterator It;
std::cin.unsetf(std::ios::skipws);
It it(std::cin), end; // input example: "2: 3.4"
MyGrammar<It, qi::space_type> gr;
TestStruct ts;
if (qi::phrase_parse(it, end, gr, qi::space, ts) && it == end)
std::cout << ts.myint << ", " << ts.mydouble << std::endl;
return 0;
}
不幸的是,编译器说:
boost_1_49_0/include/boost/spirit/home/qi/detail/assign_to.hpp:123:
error: no matching function for call to ‘TestStruct::TestStruct(const int&)’
最佳答案
是的,代码可以编译。事实上,你可以不用构造函数:默认的(编译器生成的)构造函数就可以了。
您需要做的就是将结构调整为 fusion 序列。 (作为奖励,这也适用于 karma。) 这正是使 std::pair
工作的魔法。
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/struct.hpp>
namespace qi = boost::spirit::qi;
struct TestStruct {
int myint;
double mydouble;
};
BOOST_FUSION_ADAPT_STRUCT(TestStruct, (int, myint)(double, mydouble));
template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, TestStruct(), Skipper> {
MyGrammar() : MyGrammar::base_type(mystruct) {
mystruct = qi::int_ >> ":" >> qi::double_;
}
qi::rule<Iterator, TestStruct(), Skipper> mystruct;
};
int main() {
typedef std::string::const_iterator It;
const std::string input("2: 3.4");
It it(input.begin()), end(input.end());
MyGrammar<It, qi::space_type> gr;
TestStruct ts;
if (qi::phrase_parse(it, end, gr, qi::space, ts) && it == end)
std::cout << ts.myint << ", " << ts.mydouble << std::endl;
return 0;
}
关于c++ - 如何使用 boost::spirit 将文本解析为结构体?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10457605/