是否可以从istringstream转到向量而不指定类型?

时间:2017-06-29 14:32:40

标签: c++ templates stringstream

这有效:

std::istringstream("1234") >> mystruct.member;

但是,如果我想将值push_back()转换为未知类型的向量,该怎么办?

部分解决方案:

decltype(some_vector)::value_type buf;
istringstream("1234") >> buf;
some_vector.push_back(buf);

是否可以在没有缓冲变量的情况下执行此操作?

2 个答案:

答案 0 :(得分:1)

如果您的stringstream保证包含空格分隔的元素并且对应于容器的类型,那么您可以执行类似的操作

template <typename Container>
void get_input(std::istream& is, Container& container) {
    auto val = typename std::decay_t<Container>::value_type{};
    while (is >> val) {
        container.push_back(std::move(val));
    }
}

请注意,我没有使用模板模板参数来推断容器被模板化的类型,因为使用value_type提供了与容器更强的契约。

答案 1 :(得分:1)

  

部分解决方案:

decltype(some_vector)::value_type buf;
istringstream("1234") >> buf;
some_vector.push_back(buf);
     

是否可以在没有缓冲变量的情况下执行此操作?

是的,在下面的程序中,它没有缓冲区,但需要付出代价。

在下面的程序中,创建一个迭代器,它将提取所需的值并将它们放入向量中。它没有公开创建缓冲区变量。它适用于不同类型的矢量。

#include <sstream>
#include <vector>
#include <string>
#include <iostream>
#include <iterator>

struct done_reading {};

template<typename T, typename charT>
T extract(std::basic_istream<charT>& is) {
    std::istream_iterator<T> it{is};
    if(it != decltype(it){}) {
        return *it;
    }
    throw done_reading{};
}

struct mystruct { int member{}; };

template<typename charT>
std::basic_istream<charT>& operator>>(std::basic_istream<charT>& is, mystruct& m) { is >> m.member; return is; }

std::ostream& operator<<(std::ostream& os, mystruct& m) { os << m.member; return os; }

template <typename T, typename S>
S& operator>>(S&& is, std::vector<T>& some_vector)
{
    for(;;)
        try {
        some_vector.emplace_back(extract<T>(is));
    }
    catch(done_reading)
    {
        return is;
    };
}

template<typename T>
void make_and_print()
{
    std::vector<T> some_vector;
    std::istringstream{"1234 5678 9101112"} >> some_vector;
    std::istringstream iss{"43728 754382 69548"};
    iss >> some_vector;
    for(auto&& i : some_vector)
        std::cout << i << '\n';
}

int main()
{
    make_and_print<int>();
    make_and_print<mystruct>();
}