【发布时间】:2018-05-01 10:44:13
【问题描述】:
我使用一个包含匿名联合和标签的类实现了一个标记联合:
class LogFile
{
public:
LogFile(std::ostream& stdStream);
LogFile(std::ofstream fileStream);
LogFile(LogFile&& logFile);
~LogFile();
std::ostream& getStream();
private:
enum { STD_STREAM, FILE_STREAM } streamType_;
union
{
std::ostream *stdStream_;
std::ofstream fileStream_;
};
};
我在实现移动构造函数时遇到了麻烦。在重载的“普通”构造函数中,我知道要初始化哪个联合成员:
LogFile::LogFile(std::ofstream fileStream)
: streamType_(FILE_STREAM), fileStream_(std::move(fileStream))
{
}
但是在移动构造函数中,我怎么知道我必须初始化stdStream_ 或fileStream_ 中的哪一个。我无法检查初始化列表中streamType_ 的值。
【问题讨论】:
-
顺便说一句,您可以将这两个成员存储在
std::ostream指针或引用中以避免联合。 -
如果您的目的是学习如何在这种棘手的情况下进行正确的移动构造,那么这是一回事。但是,如果您的真正目的是让这个工作正常进行,请将这个 union 替换为
std::variant并让它为您完成所有的思考。 -
std::variant对我来说太新了,我的编译器还不支持。在我的特殊情况下,我最终使用了@Rakete1111 建议的std::unique_ptr<std::ostream>。对于stdout,您需要在堆上创建一个std::ostream的新实例,其底层缓冲区为std::cout:std::unique_ptr<std::ostream>(new std::ostream(std::cout.rdbuf()))(否则std::unique_ptr将尝试删除静态分配的std::cout)
标签: c++ c++11 unions move-constructor