【问题标题】:Declaration works with auto but not by explicitly declaring the type? [duplicate]声明适用于 auto 但不是通过显式声明类型? [复制]
【发布时间】:2019-02-22 11:58:54
【问题描述】:

我有以下课程:

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&lt;connection, manager&gt; conn;

clang 返回错误:

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

这两者不应该互换吗?

【问题讨论】:

    标签: c++ c++11


    【解决方案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.
    }
    

    【讨论】:

      【解决方案2】:

      这两者不应该互换吗?

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-08-31
        • 2023-03-29
        • 1970-01-01
        • 1970-01-01
        • 2014-12-10
        • 2013-10-14
        相关资源
        最近更新 更多