如何将boost空流shared_ptr转换为std::ofstream的shared_ptr?
核心问题分析
你尝试将boost::iostreams::stream<boost::iostreams::null_sink>转换为shared_ptr<std::ofstream>失败,本质是因为这两个类型同属std::ostream的子类,但互相没有继承关系,因此dynamic_pointer_cast无法完成转换。虽然boost空流可以赋值给std::ostream&(基类引用指向子类对象的多态特性),但这并不代表它们能直接跨类型转换为std::ofstream的智能指针。
下面提供几种跨平台的可行方案,按推荐优先级排序:
方案1:重构成员变量类型(最优解)
将成员变量shared_ptr<std::ofstream>改为shared_ptr<std::ostream>,利用多态特性兼容正常输出流和空流:
正常初始化代码(无需大幅修改)
InputReader::InputReader(std::string filepath2, std::string filepathmain){ this->thestreamstruct.themainWriter = std::make_shared<std::ofstream>(filepathmain.c_str()); }
抑制输出的初始化代码
InputReader::InputReader(std::string filepath2, Model* amodel){ auto null_stream = std::make_shared<boost::iostreams::stream<boost::iostreams::null_sink>>(boost::iostreams::null_sink{}); this->thestreamstruct.themainWriter = null_stream; }
boost::iostreams::stream<boost::iostreams::null_sink>继承自std::ostream,因此shared_ptr<std::ostream>可以直接接收它的智能指针,完全满足抑制输出的需求,且代码简洁高效。
方案2:自定义空std::ofstream子类(不修改成员变量类型)
如果无法修改成员变量的类型(必须保留shared_ptr<std::ofstream>),可以自定义一个继承自std::ofstream的空流类,重载输出操作符以忽略所有输出:
自定义空流类
#include <fstream> #include <ostream> class NullOfstream : public std::ofstream { public: NullOfstream() = default; // 重载通用输出操作符,忽略所有输出内容 template<typename T> NullOfstream& operator<<(const T&) { return *this; } // 处理std::endl这类操纵符 NullOfstream& operator<<(std::ostream& (*manip)(std::ostream&)) { manip(*this); // 调用操纵符但不实际输出 return *this; } };
抑制输出的初始化代码
InputReader::InputReader(std::string filepath2, Model* amodel){ this->thestreamstruct.themainWriter = std::make_shared<NullOfstream>(); }
这个类是std::ofstream的直接子类,因此shared_ptr<std::ofstream>可以直接接收,所有输出操作都会被静默忽略,跨平台兼容。
方案3:绕过make_shared使用ofstream(nullptr)(备选)
你提到ofstream(nullptr)在make_shared中无法编译,但可以直接用shared_ptr的构造函数创建:
InputReader::InputReader(std::string filepath2, Model* amodel){ this->thestreamstruct.themainWriter = std::shared_ptr<std::ofstream>(new std::ofstream(nullptr)); }
不过这个方案依赖标准库对ofstream(nullptr)的支持,部分旧编译器或标准库版本可能存在兼容性问题,因此优先级低于前两个方案。
内容的提问来源于stack exchange,提问作者L Holness

