admin管理员组文章数量:1391987
I am trying to write a general-purpose RAII class - very similar to a smart pointer but it handles creation as well as destruction. This is the gist of it:
template <typename T>
struct dynamic_type_t {};
template <typename T>
inline constexpr dynamic_type_t<T> dynamic_type {};
template <typename T>
class RAII
{
private:
T* m_ptr;
public:
template <typename DynamicType, typename... Args>
RAII(dynamic_type_t<DynamicType>, Args&&... args) {
m_ptr = new DynamicType{std::forward<Args>(args)...};
}
~RAII() { delete m_ptr; }
};
Now, the test code works flawlessly:
#include <iostream>
struct Base
{
Base() = default;
virtual ~Base() { std::cout << "doo dtor" << '\n'; }
};
struct Derived : public Base
{
long n;
Derived(int x) : Base(), n(x) {}
~Derived() override { std::cout << "widget dtor" << '\n'; }
};
int main () {
RAII<Base> raii{dynamic_type<Derived>, 42};
return 0;
}
The mechanism behind delete
that allows this kind of polymorphic deallocation is discussed in this thread.
However, the reason I am not using smart pointers in the first place is that I need custom allocator support. But I am failing miserably to extend RAII
with this functionality. The straightforward approach:
template <typename T, template <typename> class AllocatorType = std::allocator>
class RAII
{
private:
T* m_ptr;
public:
template <typename DynamicType, typename... Args>
RAII(dynamic_type_t<DynamicType>, Args&&... args) {
using Alloc = AllocatorType<DynamicType>;
using AllocT = std::allocator_traits<Alloc>;
Alloc alloc{};
auto* ptr = AllocT::allocate(alloc, 1);
AllocT::construct(alloc, ptr, std::forward<Args>(args)...);
m_ptr = ptr;
}
~RAII() {
using Alloc = AllocatorType<T>;
using AllocT = std::allocator_traits<Alloc>;
Alloc alloc{};
AllocT::destroy(alloc, m_ptr);
AllocT::deallocate(alloc, m_ptr, 1);
}
};
obviously does not work since allocation and deallocation sizes do not match. If used with the test code from above, ASAN's new-delete-type-mismatch is triggered.
So, my question is: Is it even possible to do this in C++ and how?
In my humble opinion, it would be a big language embarrassment if new
and delete
allowed this but std::allocator
didn't.
NOTE: There is a thread with similar question but it is very old and does not provide any satisfying answers. I do not consider it to be a duplicate.
EDIT
I cannot afford any overhead compared to what would simple approach using new
and delete
incur. Is it possible to replace delete
with std::allocator
without any additional penalties?
IMPORTANT EDIT
I have found that the problem arises because std::allocator
always uses sized version of operator delete
. If one uses ::operator delete(m_ptr)
, things work as expected. This would seem to imply that std::allocator
misses an unsized overload. Does anybody know more?
本文标签: cCan stdallocator be used to handle polymorphic objectsStack Overflow
版权声明:本文标题:c++ - Can `std::allocator` be used to handle polymorphic objects? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744706255a2620860.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论