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

时间:2018-09-13 16:38:11

标签: c++ templates c++17

我正在尝试使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中的那个人是如何工作的呢?

1 个答案:

答案 0 :(得分: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";
}

不再需要递归。

相关问题