为什么无法移动std::ofstream?

21

在Stack Overflow的之前回答中,似乎std::ostream是不可移动的,但std::ofstream应该是可以移动的。然而,这段代码

#include <fstream>

int main()
{
    std::ofstream ofs;
    std::ofstream ofs2{std::move(ofs)};
}

似乎在我尝试的任何版本的gcc或clang中都无法编译(使用--std=c++11或--std=c++14)。编译器错误略有不同,但这是我在gcc 4.9.0中得到的结果:

6 : error: use of deleted function 'std::basic_ofstream::basic_ofstream(const std::basic_ofstream&)'

这是否符合标准的预期行为?
请注意,先前有一个非常类似的问题(std::ofstream可移动吗?),但似乎标准自那时以来已经改变了(如为什么std::ostream不能被移动?所述),使那些答案过时。当然,没有一个答案能解释上面的代码为什么无法编译。
尝试使用ofstream容器时遇到此问题,因为上述原因而无法正常工作。

2
在FreeBSD上使用--std=c++11,Clang 3.4.1可以很好地编译。 - jbruni
1个回答

19
根据标准
27.9.1.11 basic_ofstream构造函数 或其更 "可读"版本 http://en.cppreference.com/w/cpp/io/basic_ofstream/basic_ofstream std::basic_ostream<>具有移动构造函数,因此代码应该编译。 使用-std=c++11-std=c++1y,clang ++ 3.5可以编译它。同时gcc5也可以编译它,因此在gcc<5的libstdc ++中可能没有实现移动语义。 有趣的是,缺乏移动语义在gcc的stdlibc ++实现中没有被提到 https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.2014 。请参见 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54316 了解错误报告,感谢@BoBTFish指出。已确认该问题已在gcc5中修复。

2
请注意,顶部只提到了 stringstream,但在更深入的地方可以明确地看出这也适用于 ofstream。底部条目为“已修复于 GCC 5”。 - BoBTFish
嗯,那看起来相当明确。我没有尝试过gcc5,但是我尝试了使用http://gcc.godbolt.org/的clang 3.5,它没有工作,我猜这是该网站的问题。感谢您的答案! - toth
@toth,我看了一下你链接中的代码,发现你正在使用std::is_lvalue_reference_v。据我所知,在C++11/14中没有这样的using,因此你必须使用std::is_value_reference<U>::value。我知道,他们应该定义它,类似于类型特征_t(来自<>::type)。 - vsoftco

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