在 std::unique_ptr 类成员上流式传输

ostream on a std::unique_ptr class member

本文关键字:成员 传输 ptr std unique      更新时间:2023-10-16

我想打印一个 std::unique_ptr 它是 Bar 的类成员。但是,以下代码不起作用,请参阅我对流 <<bar.foo_unique() 的评论;我想我应该更改我的 foo_unique() 访问器,但我不知道如何。

#include <iostream> 
#include <memory>
class Foo
{
public:
    Foo() : n_(1) {}
    int n() const { return n_; }
private:
    int n_;
};
std::ostream& operator<< (std::ostream& stream, const Foo& foo);
std::ostream& operator<< (std::ostream& stream, const Foo& foo)
{
    stream << foo.n();
    return stream;
}
class Bar 
{
public:
    Bar() : m_(2), foo_(), foo_unique_(std::make_unique<Foo>()) {}
    int m() const { return m_; }
    const Foo& foo() const { return foo_; }
    const std::unique_ptr<Foo>& foo_unique() const { return foo_unique_; }   // what to return here ?
private:
    int m_;
    Foo foo_;                         
    std::unique_ptr<Foo> foo_unique_;  
};
std::ostream& operator<< (std::ostream& stream, const Bar& bar);
std::ostream& operator<< (std::ostream& stream, const Bar& bar)
{
    stream << bar.m() << ",";
    stream << bar.foo();
    // stream << bar.foo_unique(); // does not work !!!
    return stream;
}
int main()
{
    Bar bar;
    std::cout << bar << std::endl;
}

我怎样才能正确地做到这一点?

编辑:我想要流<<bar.foo_unique(); 具有与流<<bar.foo() 相同的行为;

没有为std::unique_ptr<T>定义输出运算符:这有点可悲,但许多C++类缺少输出运算符。最简单的方法是只打印指针:

stream << bar.foo_unique().get();

如果要打印实际指针,或者取消引用指针

stream << *bar.foo_unique();

如果您想打印足尖。

要使用输出运算符

,您可以创建自己的输出运算符,假设Foo是用户定义的类型,std::unique_ptr<Foo>。您可以将其放入与定义Foo相同的命名空间中:

std::ostream& operator<< (std::ostream& out, std::unique_ptr<Foo> const& foo) {
    return out << *foo; // or foo.get()depending on what you want to get printed
}

没有从 std::unique_ptr<T>T const& 的隐式转换,这会阻止确定流插入运算符。不过,您在这里有几个选择。第一个选项是为std::unique_ptr<T>提供一次operator<<覆盖,为T&提供一次覆盖。如果您同时使用std::unique_ptr和非拥有原始指针或引用,这可能会变得乏味。第二个选项是提供单个模板化版本的operator<<来处理std::unique_ptr<T>的实例,然后提供单个版本来处理T const&。下面是如何实现此目的的示例。

std::ostream& operator<< (std::ostream& out, Foo const& arg)
{
    // output stuff here
    return out;
}
template<class T>
std::ostream& operator<< (std::ostream& out, std::unique_ptr<T> const& arg)
{
    return out << *arg;
}