在模板化类中使用shared_from_this

nij*_*sen 21 c++ templates shared-ptr c++11

我有一个资源管理器,像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_;
};
Run Code Online (Sandbox Code Playgroud)

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

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;
        }
};
Run Code Online (Sandbox Code Playgroud)

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

这是存储策略的示例:

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_;
};
Run Code Online (Sandbox Code Playgroud)

但我得到一个编译错误:

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>’
Run Code Online (Sandbox Code Playgroud)

有关完整编译输出,请参阅最小示例.

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

Jon*_*ely 48

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.