Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is overriding both the global new operator and the class-specific operator not ambiguous behaviour?

Consider the following code:

class Foo 
{
public:
    //class-specific
    Foo operator+(Foo& rhs)
    {
       return Foo(); //Just return a temporary
    }

    void* operator new(size_t sd)
    {
        return malloc(sd);
    }
};

//global
Foo operator+(Foo& lhs, Foo& rhs)
{
    return Foo();
}

void* operator new(size_t sd)
{
    return malloc(sd);
}

This code will not compile, stating the call is ambiguous because it matches two operators:

Foo a, b;
a + b;

But this one with the new operator compiles just fine, and will call the class-specific one.

Foo* a = new Foo();

Why doesn't it result in a compile error? Does the compiler treat the new operator differently? (Any citation to the standard would be appreciated.)

like image 946
yggdrasil Avatar asked Sep 28 '18 11:09

yggdrasil


People also ask

How does the compiler differentiates the class specific function and a global function?

How does the compiler differentiates the class-specific function and a global function? To map the function call with the corresponding function definition, the compiler performs the process of name-lookup. This process yields some set of functions that have the same name and they are called candidate functions.

What does the new operator do c++?

The new operator is an operator which denotes a request for memory allocation on the Heap. If sufficient memory is available, new operator initializes the memory and returns the address of the newly allocated and initialized memory to the pointer variable.

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.

How to use new operator?

Use of the new operator signifies a request for the memory allocation on the heap. If the sufficient memory is available, it initializes the memory and returns its address to the pointer variable. The new operator should only be used if the data object should remain in memory until delete is called.


2 Answers

Why doesn't it result in a compile error? Does the compiler treat the new operator differently? (Any citation to the standard would be appreciated)

Regarding the precedence between global new and class specific new, the reference says this:

As described in allocation function, the C++ program may provide global and class-specific replacements for these functions. If the new-expression begins with the optional :: operator, as in ::new T or ::new T[n], class-specific replacements will be ignored (the function is looked up in global scope). Otherwise, if T is a class type, lookup begins in the class scope of T.

So class specific new has priority.

Regarding the overload of +, you can either have the member overload or the global overload (usually as a friend of the class) but not both because of the ambiguity it produces.

like image 175
P.W Avatar answered Jan 01 '23 21:01

P.W


The class' operator new is always preferred if defined:

[expr.new]/9

If the new-expression begins with a unary ​::​ operator, the allocation function's name is looked up in the global scope. Otherwise, if the allocated type is a class type T or array thereof, the allocation function's name is looked up in the scope of T. If this lookup fails to find the name, or if the allocated type is not a class type, the allocation function's name is looked up in the global scope.

It can be tricky to read: if the new-expression does not begins with :: and the allocated type is a class type, then new is looked up in the class' scope.

like image 40
YSC Avatar answered Jan 01 '23 22:01

YSC