为什么`std :: istream_iterator`没有rvalue构造函数?

时间:2016-10-31 09:52:32

标签: c++ c++11 iterator rvalue-reference

std::istream_iterator是否有任何特定原因无法将流作为右值接收?

为了传递临时对象,我必须创建一个类似的函数:

template<class T, class ostream_t>
std::istream_iterator<T> my_it(ostream_t&& ostream)
{ return {ostream}; }

template<class T>
std::istream_iterator<T> my_it() { return {}; }

int main()
{
    std::string file("3.45 1.23 7,56");

    std::copy(my_it<double>(std::istringstream(file)), my_it<double>(),
              std::ostream_iterator<double>(std::cout, " "));
}

然而,这将更方便,更短:

int main()
{
    std::string file("3.45 1.23 7,56");

    using my_it = std::istream_iterator<double>;

    std::copy(my_it(std::istringstream(file)), my_it(),
              std::ostream_iterator<double>(std::cout, " "));
}

为什么在三次标准更新(C ++ 11,C ++ 14和C ++ 17)之后,对于那种迭代器没有rvalue构造函数,几乎每种其他类型都有它?

你可以争辩说,由于迭代器是可复制的并且包含引用,如果引用的对象不再存活,你可以获得未定义的行为(std::reference_wrapper也禁用了rvalue构造),但是也可以与左值参考一起发生。

毕竟,这是用户的土地责任。

1 个答案:

答案 0 :(得分:-3)

我认为您的回答是page 74 of Modern C++

  

例如,istream对象表示输入值流,其中一些可能已经被读取,其中一些可能稍后被读取。如果要复制一个istream,是否需要复制已经读取的所有值以及将来读取的所有值?处理这些问题的最简单方法是将它们定义为不存在。禁止复制流就是这样。

==编辑==

哦,我完全误解了你的问题!我现在明白你对临时价值的意思了。让我只粘贴你的程序的两个版本,以突出问题。

这不编译:

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

int main()
{
    std::string file("3.45 1.23 7,56");

    using my_it = std::istream_iterator<double>;

    std::copy(my_it(std::istringstream(file)), my_it(),
            std::ostream_iterator<double>(std::cout, " "));
}

但这样做:

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

int main()
{
    std::string file("3.45 1.23 7,56");

    using my_it = std::istream_iterator<double>;

    std::istringstream a(file);
    std::copy(my_it(a), my_it(), std::ostream_iterator<double>(std::cout, " "));
}