如何检测类型是否有重载版本的operator new和delete?

时间:2015-10-06 04:47:27

标签: c++ c++11 memory-management operator-overloading new-operator

实现我发现的自定义分配器,对于重载LEFT JOINvoid * operator new(std::size_t)分配器void operator delete(void *)的类不使用所提及的运算符的重载版本,但它使用全局定义的版本。 Documentation of std::allocator说:

  

通过调用std::allocator为未初始化的存储分配n * sizeof(T)个字节,但未指定何时以及如何调用此函数。

我认为可以通过::operator new(std::size_t)或类似的方式使用SFINAE进行重载,以便调度std::is_class< value_type >{} || std::is_union< value_type >{}是否可以(曾经)提供运算符的重载版本并最终使用它们的正确版本。但是以这种形式使用谓词是不够的。

std::allocator_traits< A >::value_type

#include <type_traits> #include <memory> #include <new> #include <vector> #include <iostream> #include <cstdlib> #include <cstddef> #define PP { std::cout << __PRETTY_FUNCTION__ << std::endl; } #define ENABLE std::enable_if_t< (std::is_class< type >{} || std::is_union< type >{}) > * = nullptr #define DISABLE std::enable_if_t< !(std::is_class< type >{} || std::is_union< type >{}) > * = nullptr template< typename type > void * operator new(std::size_t n, ENABLE) noexcept(false) { return type::operator new(n); } template< typename type > void * operator new(std::size_t n, DISABLE) noexcept(false) { PP; return ::operator new(n); } template< typename type > void operator delete(void * p, ENABLE) noexcept { return type::operator delete(p); } template< typename type > void operator delete(void * p, DISABLE) noexcept { PP; return ::operator delete(p); } template< typename type > struct allocator { using value_type = type; value_type * allocate(std::size_t n) noexcept(false) { return static_cast< value_type * >(::operator new< value_type >(n)); } void deallocate(value_type * p, std::size_t /*n*/) noexcept { return ::operator delete< value_type >(p); } template< typename rhs > constexpr bool operator == (allocator< rhs > const & /*_rhs*/) noexcept { return true; } template< typename rhs > constexpr bool operator != (allocator< rhs > const & _rhs) noexcept { return !operator == (_rhs); } }; struct A { void * operator new(std::size_t n) noexcept(false) { PP; return ::operator new(n); } void operator delete(void * p) noexcept { PP; return ::operator delete(p); } }; struct B {}; int main() { { std::vector< A, allocator< A > > a; a.resize(1); } std::cout << std::endl; { std::vector< int, allocator< int > > i; i.resize(1); } std::cout << std::endl; { //std::vector< B, allocator< B > > b; //b.resize(1); } return EXIT_SUCCESS; } 类型和A类型的输出为:

int

即。调度是正确的,但对于static void *A::operator new(std::size_t) static void A::operator delete(void *) void *operator new(std::size_t, std::enable_if_t<!(std::is_class<type>({}) || std::is_union<type>({}))> *) [type = int] void operator delete(void *, std::enable_if_t<!(std::is_class<type>({}) || std::is_union<type>({}))> *) [type = int] 类,发生了错误:

B

如何检测类范围main.cpp:34:22: error: no member named 'operator delete' in 'B' return type::operator delete(p); ~~~~~~^ main.cpp:60:22: note: in instantiation of function template specialization 'operator delete<B>' requested here return ::operator delete< value_type >(p); ^ /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/bits/alloc_traits.h:386:13: note: in instantiation of member function 'allocator<B>::deallocate' requested here { __a.deallocate(__p, __n); } ^ /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/bits/stl_vector.h:178:9: note: in instantiation of member function 'std::allocator_traits<allocator<B> >::deallocate' requested here _Tr::deallocate(_M_impl, __p, __n); ^ /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/bits/stl_vector.h:160:9: note: in instantiation of member function 'std::_Vector_base<B, allocator<B> >::_M_deallocate' requested here { _M_deallocate(this->_M_impl._M_start, this->_M_impl._M_end_of_storage ^ /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/bits/stl_vector.h:253:7: note: in instantiation of member function 'std::_Vector_base<B, allocator<B> >::~_Vector_base' requested here vector() ^ main.cpp:116:46: note: in instantiation of member function 'std::vector<B, allocator<B> >::vector' requested here std::vector< B, allocator< B > > b; ^ main.cpp:19:22: error: no member named 'operator new' in 'B' return type::operator new(n); ~~~~~~^ main.cpp:54:50: note: in instantiation of function template specialization 'operator new<B>' requested here return static_cast< value_type * >(::operator new< value_type >(n)); ^ /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/bits/alloc_traits.h:360:20: note: in instantiation of member function 'allocator<B>::allocate' requested here { return __a.allocate(__n); } ^ /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/bits/stl_vector.h:170:25: note: in instantiation of member function 'std::allocator_traits<allocator<B> >::allocate' requested here return __n != 0 ? _Tr::allocate(_M_impl, __n) : pointer(); ^ /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/bits/vector.tcc:557:34: note: in instantiation of member function 'std::_Vector_base<B, allocator<B> >::_M_allocate' requested here pointer __new_start(this->_M_allocate(__len)); ^ /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/bits/stl_vector.h:676:4: note: in instantiation of member function 'std::vector<B, allocator<B> >::_M_default_append' requested here _M_default_append(__new_size - size()); ^ main.cpp:117:15: note: in instantiation of member function 'std::vector<B, allocator<B> >::resize' requested here b.resize(1); ^ 2 errors generated. operator new的重载版本的存在?

0 个答案:

没有答案