std :: unique_ptr类成员上的ostream

时间:2015-01-11 23:01:21

标签: c++ c++14 unique-ptr

我想打印一个std :: unique_ptr,它是Bar的一个类成员。 但是,以下代码无效,请参阅我对 stream<<的评论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;
}

我该如何正确地做到这一点?

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

2 个答案:

答案 0 :(得分:8)

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

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

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

stream << *bar.foo_unique();

如果你想打印指针。

要使用输出运算符,您可以使用std::unique_ptr<Foo>创建自己的输出运算符,假设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
}

答案 1 :(得分:0)

没有从std::unique_ptr<T>T const&的隐式转换阻止了流插入运算符的确定。你有几个选择。第一个选项是为operator<<提供一个std::unique_ptr<T>覆盖,为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;
}