使用std :: visit示例堆栈溢出

问题描述 投票:0回答:1

我试图让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的家伙如何使它发挥作用?

c++ templates c++17
1个回答
2
投票

这是一个不需要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";
}

而且没有更多的递归。

© www.soinside.com 2019 - 2024. All rights reserved.