从 istream 读取 boost::variant 类型

3

我正在研究 boost::variant,想知道如何使以下内容工作?

typedef boost::variant<int,std::string> myval;
int main()
{

std::vector<myval> vec;

std::ifstream fin("temp.txt");

//How following can be achieved ?
std::copy(std::istream_iterator<myval>(fin), //Can this be from std::cin too ?
          std::istream_iterator<myval>(),
          std::back_inserter(vec));   
}

对于类的数据成员,我们可以重载>>运算符,但是如何在myval中实现呢?

2个回答

3
您可以像对其他类型一样过载operator>>,用于variant。但是,您需要自己实现逻辑来决定从流中读取和存储在variant中的类型。以下是一个完整的示例,展示了如何处理它:
#include "boost/variant.hpp"
#include <iostream>
#include <cctype>
#include <vector>
#include <string>

typedef boost::variant<int, std::string> myval;

namespace boost { // must be in boost namespace to be found by ADL
std::istream& operator>>(std::istream& in, myval& v)
{
    in >> std::ws;      // throw away leading whitespace
    int c = in.peek();
    if (c == EOF) return in;  // nothing to read, done

    // read int if there's a minus or a digit
    // TODO: handle the case where minus is not followed by a digit
    // because that's supposed to be an error or read as a string
    if (std::isdigit(static_cast<unsigned char>(c)) || c == '-') {
        int i;
        in >> i;
        v = i;
    } else {
        std::string s;
        in >> s;
        v = s;
    }
    return in;
}
} // namespace boost

// visitor to query the type of value
struct visitor : boost::static_visitor<std::string> {
    std::string operator()(const std::string&) const
    {
        return "string";
    }
    std::string operator()(int) const
    {
        return "int";
    }
};

int main()
{
    std::vector<myval> vec;
    std::copy(
        std::istream_iterator<myval>(std::cin),
        std::istream_iterator<myval>(),
        std::back_inserter(vec));

    std::cout << "Types read:\n";
    for (const auto& v : vec) {
        std::string s = boost::apply_visitor(visitor(), v);
        std::cout << s << '\n';
    }
}

示例输入:1 2 3 hello 4 world

输出:

Types read:
int
int
int
string
int
string

这是一个非常好的方法。但由于某些原因,我得到了所有的“string”。我正在使用MingW 4.7.2。 - P0W
@P0W 您的意思是输出中所有字符串吗?即使您输入整数并使用我发布的精确代码? - jrok
@P0W 不用在意,if语句里有一个愚蠢的错误,已经修复了。 - jrok

0

myval 只是一种类型。你可以根据类型重载运算符。

std::istream &operator >>(std::istream &stream, myval &val)
{
    //Put stuff here.
}

至于要放什么,那完全取决于您以及您希望或需要在流中有什么。


3
这个操作符会参与名称查找吗?恐怕您需要将它放在 boost 或者 std 命名空间中。 - Igor R.
@NicolBolas std::istream &operator >>(std::istream &stream, myval &val) { return stream>>val; } 无法编译。 然而,经过重载后,myval x; std::cin>>x; 可以编译,但可执行文件会崩溃。 - P0W
@NicolBolas,谢谢,现在我明白你是如何通过与jrok的例子进行关联来表达你的意思的。 - P0W

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接