实现我发现的自定义分配器,对于重载LEFT JOIN
和void * 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
的重载版本的存在?