Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declaration works with auto but not by explicitly declaring the type? [duplicate]

Tags:

c++

c++11

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?

like image 868
ruipacheco Avatar asked Nov 06 '22 20:11

ruipacheco


1 Answers

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.
}
like image 171
molbdnilo Avatar answered Nov 15 '22 07:11

molbdnilo