31

我有一个资源管理器,就像 Andrei Alexandrescu 在 Modern C++ Design 一书中提出的那样,遵循基于策略的设计。不过我遇到了麻烦,因为我的资源管理器需要能够通过shared_from_this().

我构建了一个重现我的问题的最小示例,您可以在此处看到结果。

基本上我有一些托管资源需要引用其管理器:

template <typename T>
class managed_resource
{
        typedef std::shared_ptr<manager<T>> manager_ptr;
    public:
        managed_resource(manager_ptr const & parent)
            : parent_(parent)
        {
        }

        /* ... */

    private:
        manager_ptr parent_;
};

以及存储和提供资源的经理:

template <typename Policy>
class manager
    : Policy
    , std::enable_shared_from_this<manager<Policy>>
{
        typedef managed_resource<Policy> resource;
        typedef std::shared_ptr<resource> resource_ptr;
    public:
        resource_ptr get_resource(std::string const & name)
        {
            Policy & p = *this;
            if(p.find(name))
            {
                return p.get(name);
            }
            resource_ptr res = std::make_shared<resource>(shared_from_this());
            p.store(name, res);
            return res;
        }
};

如您所见,存储本身是基于策略的。虽然经理确实创建了资源,但策略可以在存储信息的各种方法之间自由决定(例如,它可以选择不存储任何内容并每次都创建新资源)。

这是存储策略的示例:

class map_policy
{
        typedef std::shared_ptr<managed_resource<map_policy>> resource_ptr;
        typedef std::map<std::string, resource_ptr> resources;

    public:
        bool find(std::string const & name)
        {
            resources::iterator res_it = resources_.find(name);
            return res_it != resources_.end();
        }

        resource_ptr get(std::string const & name)
        {
            resources::iterator res_it = resources_.find(name);
            return res_it->second;
        }

        void store(std::string const & name, resource_ptr const & res)
        {
            resources_[name] = res;
        }

    private:
        resources resources_;
};

但我得到一个编译错误:

error: there are no arguments to ‘shared_from_this’ that depend 
       on a template parameter, so a declaration of 
       ‘shared_from_this’ must be available
error: ‘std::enable_shared_from_this<manager<map_policy> >’ is 
       an inaccessible base of ‘manager<map_policy>’

有关完整的编译输出,请参见最小示例

是否不可能在基于策略的设计中使用std::enable_shared_from_this和使用?shared_from_this()如果没有,正确的使用方法是什么?

4

3 回答 3

65

enable_shared_from_this<manager<Policy>>是一个“依赖基类”(在这种情况下,它是一个类型取决于模板参数的基类Policy)所以 C++ 的规则说非限定名称查找不会在那里查找,您需要说this->shared_from_this()std::enable_shared_from_this<manage<Policy>>::shared_from_this()从中查找成员依赖的基础。

请参阅http://gcc.gnu.org/wiki/VerboseDiagnostics#dependent_base了解更多详细信息和其他参考资料的链接。

要修复第二个错误,您需要创建enable_shared_from_this一个公共基类,否则当管理器由shared_ptr.

于 2013-07-25T08:57:56.690 回答
4

编译器告诉您问题是从属名称查找与非从属名称查找。“依赖”的意思是“依赖于模板参数”。

在(首先)解析模板定义时查找非依赖名称,而仅在实例化模板时查找依赖名称(及其成员)。

在您的情况下,名称shared_from_this不依赖于任何模板参数,因此编译器希望在解析模板时访问它。但是,您的类从 中获取它enable_shared_from_this<manager<Policy>>,这确实取决于模板参数,因此仅在实例化时进行查看。

你必须shared_from_this变成一个依赖的名字。你有两个选择:

  1. 用依赖的东西来限定它。最简单的是使用this->shared_from_this().

  2. 通过将 using-declaration 放入类定义中,将其显式纳入范围:using std::enable_shared_from_this<manager<Policy>>::shared_from_this;

于 2013-07-25T09:01:53.520 回答
-2

正如其他人所写,您必须使用this->shared_from_this(). 但这并没有真正的帮助。我已经进一步编辑了您的代码并将所有内容公开(全部classesstructs和不publicprivate...)。现在它编译。有时在进行原型设计时最好不要考虑限制对成员的访问(因为它会导致更多的编译错误)。这可以稍后在测试正常时完成。

于 2013-07-25T09:09:39.027 回答