5

I have the following class:

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>;
}

where connection has the same visibility as pool.

In my tests I can use borrow() with auto:

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

but I can't declare a variable with the same type as the return type of borrow():

std::unique_ptr<connection, manager> conn;

with clang returning the error:

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

Shouldn't these two be interchangeable?

ruipacheco
  • 15,025
  • 19
  • 82
  • 138

2 Answers2

1

You can declare the variable you want if you use decltype:

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

Access control applies to names, not definitions or data.

Even though the name of the type is private, you're allowed to use the type as long as you don't name it.

Here's an example without 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.
}
molbdnilo
  • 64,751
  • 3
  • 43
  • 82
0

Shouldn't these two be interchangeable?

No, not necessarily. A private struct is to be considered an implementation detail, so it can be removed or renamed in future versions of your class. So, nobody (outside the class) is allowed to spell the name of the private struct.

If a member functions of the class returns objects of that private type, there needs to be a way to work with these objects. One possibility to do so, is the auto keyword. (Alternatives are decltype and function templates. The latter existed before C++11.) Note that the auto keyword would also work if you decide to rename the private struct.

Handy999
  • 766
  • 4
  • 8