声明可与auto一起使用,但不能通过显式声明类型来实现?

时间:2019-02-22 11:58:55

标签: c++ c++11

我有以下课程:

struct pool : public std::enable_shared_from_this<pool> {
     private:
      struct manager {
        explicit manager(const std::weak_ptr<pool> &pool) : m_pool{pool} {
        }
        explicit manager() = default;
        auto operator()(connection *conn) -> void;

       private:
        std::weak_ptr<pool> m_pool;
      };

     public:
      pool(const pool &) = delete;
      auto operator=(const pool &) -> pool & = delete;

      auto borrow() noexcept -> std::unique_ptr<connection, manager>;
}

其中connectionpool具有相同的可见性。

在测试中,我可以将borrow()与auto一起使用:

auto p = std::make_shared<pool>();
auto conn = p->borrow();

但是我无法声明与返回类型borrow()相同类型的变量:

std::unique_ptr<connection, manager> conn;

clang返回错误:

error: 'manager' is a private member of 'dbc::detail::pool'

这两个不是可互换的吗?

2 个答案:

答案 0 :(得分:1)

如果使用decltype,您可以声明所需的变量:

decltype(p->borrow()) conn = p->borrow();

访问控制适用于名称,而不适用于定义或数据。

即使类型的名称是私有的,只要您不命名,就可以使用它。

下面是一个没有auto的示例:

class A
{
    struct B { int x; } m_b;
public:
    B f() { return m_b; }
};

int main()
{
    A a;
    std::cout << a.f().x; // Compiles, since 'A::B::x' is public.
    decltype(a.f()) b1; // Compiles, since the name 'B' is not used.
    A::B b; // Doesn't compile, since the name is private.
}

答案 1 :(得分:0)

  

这两个不是可互换的吗?

不,不一定。私有结构将被视为实现细节,因此可以在类的将来版本中将其删除或重命名。因此,不允许任何人(在类外部)拼写私有结构的名称。

如果类的成员函数返回该私有类型的对象,则需要一种使用这些对象的方法。这样做的一种可能是关键字auto。 (替代方法是decltype和函数模板。后者在C ++ 11之前存在。)请注意,如果您决定重命名私有结构,则auto关键字也将起作用。