Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Placement new With Overloaded Ordinary new Operator

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 #includeing?) 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?

like image 406
imallett Avatar asked Oct 07 '15 18:10

imallett


People also ask

How do you overload a new placement?

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.

Can we create new operators using overloaded operator function?

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.

What should the first parameter for an overloaded new operator?

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).

What is :: operator new?

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.


1 Answers

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);
like image 50
R Sahu Avatar answered Sep 16 '22 16:09

R Sahu