Mam menedżera zasobów, który podobnie jak Andrei Alexandrescu zaproponowany w książce Modern C++ Design, jest oparty na zasadach. Mam jednak problem, ponieważ mój menedżer zasobów musi być w stanie przekazać sobie odniesienia do zarządzanych zasobów przez shared_from_this()
.Używanie shared_from_this w klasach szablonowych
Zbudowałem minimalny przykład odtwarzający mój problem, którego wyniki można zobaczyć here.
Zasadniczo mam niektóre udało zasobem, który potrzebuje odniesienie do jego zarządcy:
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_;
};
i kierownik, który przechowuje i udostępnia zasoby:
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;
}
};
Jak widać, przechowywania sobie jest oparte na polityce. Podczas gdy menedżer tworzy zasoby, polityka może dowolnie decydować pomiędzy różnymi podejściami do przechowywania informacji (może np. Zdecydować, że nie będzie niczego przechowywać i tworzyć nowe zasoby za każdym razem).
Jest to przykład polityki magazynowej:
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_;
};
Ale pojawia się błąd kompilacji:
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>’
do pełnego wyjścia kompilacji zobaczyć minimal example.
Czy korzystanie z std::enable_shared_from_this
i shared_from_this()
jest niemożliwe w ramach projektu opartego na zasadach? Jeśli nie, jaki jest właściwy sposób korzystania z niego?
manager_ptr const & parent? –