如何拥有 "factory function" return 一个不可复制的对象?
How to have "factory function" return a non copyable object?
上下文
尝试创建一些内部具有不同文件名的 gzip 存档,我编写了以下代码片段。
#include <iostream>
#include <utility>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filter/gzip.hpp>
boost::iostreams::filtering_ostream&& makeGZipStream(const std::string& archiveName,
const std::string& fileName)
{
boost::iostreams::filtering_ostream theGzipStream;
boost::iostreams::gzip_params theGzipParams;
theGzipParams.file_name = fileName;
theGzipStream.push(boost::iostreams::gzip_compressor{theGzipParams});
theGzipStream.push(boost::iostreams::file_sink{archiveName});
return std::move(theGzipStream);
}
int main()
{
boost::iostreams::filtering_ostream&& theGzipStream = makeGZipStream("archive.gz", "file");
theGzipStream << "This is a test..." << std::endl;
return 0;
}
问题
这(如我们所料)会产生一个核心转储,因为在 makeGZipStream
中我们试图通过(右值)引用 return 一个本地堆栈分配的变量。但在这种情况下,复制不是一个选项,因为 boost::iostreams::filtering_ostream
是不可复制的。
问题
- 我们可以return a
std::unique_ptr
"by value"感谢它的移动构造函数(由于复制省略,移动甚至不应该在 C++17 中发生),为什么在这种情况下不可能?
- 那里有什么好的解决方案?
可能的解决方案
- 将所有内容放在同一范围内(我试图避免的)
- 将对象包裹在
unique_ptr
(不太漂亮)
- 还有什么吗?
备注
使用的编译器是很旧的g++ (GCC) 4.9.3
。
只需按值 return 并从 return 语句中删除 std::move()
:
boost::iostreams::filtering_ostream makeGZipStream(const std::string& archiveName,
const std::string& fileName)
{
...
return theGzipStream;
}
如果由于缺少移动构造函数而无法编译,那么你就不走运了,这个类型是不可移动的,所以将它包装到 std::unique_ptr
和 return 那个指针的值(哪个肯定是可以移动的)。
上下文
尝试创建一些内部具有不同文件名的 gzip 存档,我编写了以下代码片段。
#include <iostream>
#include <utility>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filter/gzip.hpp>
boost::iostreams::filtering_ostream&& makeGZipStream(const std::string& archiveName,
const std::string& fileName)
{
boost::iostreams::filtering_ostream theGzipStream;
boost::iostreams::gzip_params theGzipParams;
theGzipParams.file_name = fileName;
theGzipStream.push(boost::iostreams::gzip_compressor{theGzipParams});
theGzipStream.push(boost::iostreams::file_sink{archiveName});
return std::move(theGzipStream);
}
int main()
{
boost::iostreams::filtering_ostream&& theGzipStream = makeGZipStream("archive.gz", "file");
theGzipStream << "This is a test..." << std::endl;
return 0;
}
问题
这(如我们所料)会产生一个核心转储,因为在 makeGZipStream
中我们试图通过(右值)引用 return 一个本地堆栈分配的变量。但在这种情况下,复制不是一个选项,因为 boost::iostreams::filtering_ostream
是不可复制的。
问题
- 我们可以return a
std::unique_ptr
"by value"感谢它的移动构造函数(由于复制省略,移动甚至不应该在 C++17 中发生),为什么在这种情况下不可能? - 那里有什么好的解决方案?
可能的解决方案
- 将所有内容放在同一范围内(我试图避免的)
- 将对象包裹在
unique_ptr
(不太漂亮) - 还有什么吗?
备注
使用的编译器是很旧的g++ (GCC) 4.9.3
。
只需按值 return 并从 return 语句中删除 std::move()
:
boost::iostreams::filtering_ostream makeGZipStream(const std::string& archiveName,
const std::string& fileName)
{
...
return theGzipStream;
}
如果由于缺少移动构造函数而无法编译,那么你就不走运了,这个类型是不可移动的,所以将它包装到 std::unique_ptr
和 return 那个指针的值(哪个肯定是可以移动的)。