我有一个资源管理器,就像现代C ++设计一书中提出的Andrei Alexandrescu一样,遵循基于策略的设计。我遇到了麻烦,因为我的资源管理员需要能够通过shared_from_this()
向托管资源提供自己的引用。
我构建了一个复制我的问题的最小例子,结果你可以看到here。
基本上我有一些托管资源需要对其经理的引用:
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>’
有关完整编译输出,请参阅minimal example。
在基于策略的设计中是否无法使用std::enable_shared_from_this
和shared_from_this()
?如果没有,使用它的正确方法是什么?
答案 0 :(得分:46)
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
所有时,它无法初始化。< / p>
答案 1 :(得分:4)
编译器告诉您问题是依赖名称查找与非依赖名称查找。 “依赖”表示“取决于模板参数。”
在(首次)解析模板定义时查找非依赖名称,而仅在实例化模板时查找依赖名称(及其成员)。
在您的情况下,名称shared_from_this
不依赖于任何模板参数,因此编译器希望在解析模板时访问它。但是,您的类从enable_shared_from_this<manager<Policy>>
获取, 依赖于模板参数,因此仅查看实例化时间。
您必须将shared_from_this
变为从属名称。您有两种选择:
使用依赖的东西对其进行限定。最简单的方法是使用this->shared_from_this()
。
通过在您的类定义中添加using声明,明确地将其带入范围:using std::enable_shared_from_this<manager<Policy>>::shared_from_this;
答案 2 :(得分:-2)
正如其他人所写,你必须使用this->shared_from_this()
。但它没有realy help。我进一步修改了您的代码并公开了所有内容(所有classes
为structs
而没有public
,private
,...)。现在它compiles。有时,在进行原型设计时考虑限制对成员的访问权限会更好不(因为它可能导致更多的编译错误)。这可以在以后进行测试时完成。