I have an object of type MyType
that, for SSE reasons, needs to be 16-byte aligned. So, I wrote an allocator and overloaded the new
operators. Methods in MyType
:
inline static void* operator new(size_t size) {
awesome::my_allocator<MyType,16> alloc;
return alloc.allocate(size);
}
inline static void* operator new[](size_t size) { return operator new(size); }
inline static void operator delete(void* ptr) {
awesome::my_allocator<MyType,16> alloc;
alloc.deallocate(reinterpret_cast<MyType*>(ptr),0); //last arg ignored in my impl
}
inline static void operator delete[](void* ptr) { operator delete(ptr); }
Now, for cache-locality reasons, I need to copy-construct an instance into a particular piece of 64-byte-aligned memory:
void MyType::copy_into(uint8_t* ptr) const {
new (reinterpret_cast<MyType*>(ptr)) MyType(*this);
}
GCC tells me:
error: no matching function for call to ‘MyType::operator new(sizetype, MyType*)’
ICC tells me:
error : function "MyType::operator new" cannot be called with the given argument list
1> argument types are: (unsigned __int64, MyType *)
As I understand it, the placement new operator is provided by the C++ implementation (or possibly by <new>
, which I also tried #include
ing?) and simply returns its argument (new
makes memory available, and placement new is the programmer saying that the given memory is available).
Curiously, the error does not occur when the (ordinary!) new operators defined above are not in the class. Indeed, MyOtherType
, which doesn't define them, works just fine.
Question: what's going on? How should I fix it?
The most important extra-functionality for placement new overload would be to check address alignment. For example, lets assume some class requires 16-bytes alignment. Developer overloads new, new[], delete and delete[] - just to be sure everything is aligned properly.
For an operator to be overloaded, at least one of the operands must be a user-defined object. Only existing operators can be overloaded. You cannot overload new operators.
The first parameter is always an ostream object (we've mostly used cout, so far). Because of this, it cannot be defined as a member function (it would have to be a member of the ostream class, which we cannot change). The << and >> operators should always be defined as outside functions (usually friend functions).
The operator new (or better the void* operator new(size_t) variant) just allocate memory, but does not do any object construction. The new keyword calls the operator new function, but then calls the object constructor.
Since you have defined operator new
in your class, you need to use the global new
to use the placement version of it.
#include <new>
...
::new (reinterpret_cast<MyType*>(ptr)) MyType(*this);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With