我试图让this code使用添加的打印调用,但是这个程序会产生堆栈溢出:
#include <iostream>
#include <variant>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/support.hpp>
auto const unquoted_text_field = *(boost::spirit::x3::char_ - ',' - boost::spirit::x3::eol);
struct text { };
struct integer { };
struct real { };
struct skip { };
typedef std::variant<text, integer, real, skip> column_variant;
std::ostream& operator<< (std::ostream& os, column_variant const& v) {
std::visit([&os](auto const& e) { os << e; }, v);
return os;
}
struct column_value_parser : boost::spirit::x3::parser<column_value_parser> {
typedef boost::spirit::unused_type attribute_type;
std::vector<column_variant>& columns;
size_t mutable pos = 0;
struct pos_tag;
column_value_parser(std::vector<column_variant>& columns)
: columns(columns)
{ }
template<typename It, typename Ctx, typename Other, typename Attr>
bool parse(It& f, It l, Ctx& /*ctx*/, Other const& /*other*/, Attr& /*attr*/) const {
std::cout << columns[pos] << std::endl;
return true;
}
};
int main() {
std::string input = "Hello,1,13.7,XXX\nWorld,2,1e3,YYY";
std::vector<column_variant> columns = { text{}, integer{}, real{}, skip{} };
auto at = input.begin();
boost::spirit::x3::parse(at, input.end(),
(column_value_parser(columns) % ',') % boost::spirit::x3::eol);
}
这是有道理的,它被埋没在对<< operator
的递归调用中。那么,this link的家伙如何使它发挥作用?
这是一个不需要Boost.Spirit的简化示例(因此编译得更快):
#include <iostream>
#include <variant>
struct text { };
typedef std::variant<text> column_variant;
std::ostream& operator<< (std::ostream& os, column_variant const& v) {
std::visit([&os](auto const& e) { os << e; }, v);
return os;
}
int main() {
column_variant v;
std::cout << v;
}
所以当我看到你的代码时,我遇到的第一个问题是:这甚至是如何编译的?我预计它不会,并且当它发生时感到惊讶。它编译的原因实际上与你获得堆栈溢出的原因相同,这是......
这实际上是做什么的?
std::cout << text{};
没有operator<<
采取text
,对吗?但是有一个operator<<
采取的论点可以从text
构建:column_variant
!因为variant
中的所有类型都不是可独立流式处理的,所以尝试流式传输它们会导致递归调用变量流运算符。
坚持这样的事情:
std::ostream& operator<<(std::ostream& os, text) {
return os << "text";
}
而且没有更多的递归。