我有一些模板化的基类
template<typename Derived>
class Base { };
,并希望在列表中存储它的派生实例。为此,我使用using derived_handle = std::unique_ptr<void, void(*)(void*)
别名。
当我现在向列表中添加派生实例时,我可以使用静态成员函数作为deleter
class foo {
template<typename Derived, typename... Args>
void add_base(Args&&... args) {
auto derived = derived_handle{new Base{std::forward<Args>(args)..., &foo::_deleter<Derived>};
_derived.emplace_back(std::move(derived));
}
private:
template<typename Baser>
void _deleter(void* base) {
delete static_cast<Base*>(base);
}
std::vector<derived_handle> _derived{};
};
或lambda
class foo {
template<typename Derived, typename... Args>
void add_base(Args&&... args) {
auto deleter = [](auto* derived){
delete static_cast<Derived*>(derived);
}
auto derived = derived_handle{new Base{std::forward<Args>(args)..., std::move(deleter)};
_derived.emplace_back(std::move(derived));
}
private:
std::vector<derived_handle> _derived{};
};
lambda版本有什么优点/缺点是我应该知道的吗?
是时候挑战一帧了!
你在代码中做了一些错误的决定。大多数使用unique_ptr
的人,甚至在多态上下文中,根本不需要自定义删除器。您这样做的唯一原因是类型擦除,而这只是因为Base<A>
和Base<B>
是不相关的类型。
如果你真的需要Base<T>
,让它从一个具有虚拟析构函数的实际的多态(非模板化)基类继承。然后你就不需要unique_ptr<void>
(一个非常糟糕的代码气味),你可以以一种类型安全的方式使用你的列表。