在模板类中使用shared_from_this
Using shared_from_this in templated classes
我有一个资源管理器,就像Andrei Alexandrescu在《现代C++设计》一书中提出的那样,它遵循基于策略的设计。不过,我遇到了麻烦,因为我的资源管理器需要能够通过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()
吗?如果没有,正确的使用方法是什么?
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
所有时,它将无法初始化。
编译器告诉您问题是依赖名称查找与非依赖名称查找。"Dependent"表示"取决于模板参数。"
当(第一次)解析模板定义时,会查找非依赖名称,而仅当实例化模板时才会查找依赖名称(及其成员)。
在您的情况下,名称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;
正如其他人所写的,您必须使用this->shared_from_this()
。但这并没有真正的帮助。我已经进一步编辑了您的代码,并公开了所有内容(所有classes
都是structs
,没有public
、private
…)。现在它可以编译了。有时,在进行原型设计时考虑限制对成员的访问(因为这可能会导致更多的编译错误),这比而不是更好。这可以在稍后测试正常时完成。
- 如何解决"invalid conversion from 'char' to 'const char*'"
- std::async from std::async in windows xp
- 引用 std::shared:ptr 以避免引用计数
- std::is_reference from std::any
- std::time_point from and to std::string
- "No suitable conversion function from 'std::string' to 'const char *' exists"
- std::chrono::time_point from std::string
- Visual accept std::string from std::byte iterator
- C++中链表的错误"Abort signal from abort(3) (sigabrt) "
- dopen():不以 root 身份运行时"failed to map segment from shared object"
- C++ 中的"template <typename From, typename Tag> struct Alias;"是什么?
- from std::vector to adept::avector
- qt get child (Callout) from QChart
- Webassembly from Javascript
- Generate boost::uuids::uuid from boost::compute::detail::sha
- 无法使用 libtool 将 -shared 参数传递给 g++
- 什么是"Reading unbounded stream from standard input (Memory Management)"的例子
- Calling C++ dll from python
- 为什么我会收到"invalid conversion from 'Queue*/Stack*' to 'int'"错误消息?
- std::chrono 在从 main 或 from 类方法使用时给出不同的值