-1

My code (not yet released, in file iaca.hh) is on pastebin: Basile Iaca C++ new conflict I'm using GCC 4.6 on Debian/Linux/Sid AMD64 with the C++11 dialect.

g++  -std=c++0x -Wall -Wextra -g -O -flto -I/usr/local/include -o iaca.hh.gch iaca.hh 
iaca.hh:631:2: warning: #warning should implement the methods [-Wcpp]
iaca.hh: In static member function 'static IaDictionnaryItem* IaDictionnaryItem::make()':
iaca.hh:964:46: error: request for member 'operator new' is ambiguous
/usr/local/include/gc/gc_cpp.h:304:14: error: candidates are: static void* gc::operator new(size_t, void*)
/usr/local/include/gc/gc_cpp.h:296:14: error:                 static void* gc::operator new(size_t, GCPlacement)
/usr/local/include/gc/gc_cpp.h:293:14: error:                 static void* gc::operator new(size_t)
iaca.hh:675:7: error:                 static void* IaAnyValue::operator new(size_t, IaAnyValue::allocate_new_value_st)
iaca.hh:667:7: error:                 static void* IaAnyValue::operator new(size_t, size_t, IaAnyValue::allocate_new_value_st)

I can't figure out what is the right syntax for forcing operator new. I want the one from my class IaAnyValue to be called in my function IaDictionnaryItem::make at the end of my iaca.hh file

I've introduced the empty allocate_new_value to solve the ambiguity, without success.

I tried without success

IaDictionnaryItem* IaDictionnaryItem::make() {
  return new(IaAnyValue::allocate_new_value) IaDictionnaryItem;
}

and

IaDictionnaryItem* IaDictionnaryItem::make() {
  return IaAnyValue::operator new(IaAnyValue::allocate_new_value) IaDictionnaryItem;
}

From what I know, the operator new is always called with sizeof (*this) as implicit first argument, etc.

Some motivations about my question is in this question about Boehm's GC & C++. Please, don't tell me I should not use Boehm's GC. I need to use it (otherwise I won't use C++).

What is the right syntax to force the good operator new to be called?

I want the Boehm's GC allocator to be used. It is available thru the gc_cleanup class, which is in class IaItemValue : public IaAnyValue, gc_cleanup and also as the new in my class IaAnyValue (the only super-class of IaDictionnaryItem) I agree there is ambiguity, I just don't guess the syntax to force it.

So how should I code my trivial IaDictionnaryItem::make at the end of the file to get it compiled successfully?

For readability, I would prefer calling IaAnyValue::operator new with sz=sizeof(*this) i.e. sizeof(IaDictionnaryItem), gap=0 and al=allocate_new_value. I just can't figure out the syntax to force this particular one to be called (of course, I still want the constructor of IaDictionnaryItem to be called inside IaDictionnaryItem::make).

I've tried to force the gc::operator new(size_t size, GCPlacement gcp) (the gc class is inherited by  gc_cleanup from <gc/gc_cpp.h>) using

IaDictionnaryItem* IaDictionnaryItem::make() {
  return new (UseGC) IaDictionnaryItem;
}

My make function is a static function returning a new instance of my object. Remember that I'm using Beohm's GC, and it will eventually release the memory used (and delete the object) when no pointers point to it.

But I'm still getting

iaca.hh: In static member function 'static IaDictionnaryItem* IaDictionnaryItem::make()':
iaca.hh:962:22: error: request for member 'operator new' is ambiguous
/usr/local/include/gc/gc_cpp.h:304:14: error: candidates are: static void* gc::operator new(size_t, void*)
/usr/local/include/gc/gc_cpp.h:296:14: error:                 static void* gc::operator new(size_t, GCPlacement)
/usr/local/include/gc/gc_cpp.h:293:14: error:                 static void* gc::operator new(size_t)
iaca.hh:675:7: error:                 static void* IaAnyValue::operator new(size_t, IaAnyValue::allocate_new_value_st)
iaca.hh:667:7: error:                 static void* IaAnyValue::operator new(size_t, size_t, IaAnyValue::allocate_new_value_st)

Regards.

EDIT: Here is simple example of the problem:

#include <cstddef>
struct A {};
struct B { void* operator new(std::size_t, A); };

struct C {};
struct D { void* operator new(std::size_t, C); };

struct E : B, D {};

int main()
{
    //I want to use `void* D::operator new(std::size_t, C);` to allocate memory
    //but it will not compile because the call to operator new is ambiguous.
    new(C()) E;
}
Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • I'd go with the compiler on this one. It is ambiguous. Which of the three defined `new` operators do you want to call? `new (size_t, void*)`? – netcoder Nov 20 '11 at 16:34
  • 1
    If you overload the `new` and `delete` operator for your class then those operators will replace the global `new` and `delete` operators and will result in calls to your defined operators for your objects,You will not need to call them explicitly.Perhaps [this](http://stackoverflow.com/questions/7194127/how-should-i-write-iso-c-standard-conformant-custom-new-and-delete-operators) helps – Alok Save Nov 20 '11 at 16:36
  • I agree on the ambiguity (I know well enough that GCC is almost always right; I'm working on GCC myself :-). I just don't know well enough C++ tricks to force it. I've edited my question to explain a bit more. – Basile Starynkevitch Nov 20 '11 at 16:41
  • I still don't know which of the three you want to call. – netcoder Nov 20 '11 at 16:48
  • Any of them will do, they all call `GC_MALLOC`. I just can't figure out the syntax to force one particular of them 3... For readability, I would prefer calling `IaAnyValue::operator new` with `sz=sizeof(*this)`, `gap=0` and `al=allocate_new_value` but I think that if you give me one solution I could adapt. – Basile Starynkevitch Nov 20 '11 at 16:50
  • Consider producing a minimal sample which demonstrates the problem that you are having. The 1000 line file in pastebin is a lot to sift through, and it is not even complete (even though it contains a lot of irrelevant stuff). – Mankarse Nov 20 '11 at 16:55
  • It is complete enough to be compiled as a header file. – Basile Starynkevitch Nov 20 '11 at 16:57
  • @BasileStarynkevitch: It doesn't even contain a main function (unless one is being generated by macros in some hidden way). I have been looking at it for 10 minutes now, and I haven't even been able to find the relevant part of the code. – Mankarse Nov 20 '11 at 17:08
  • It's not a complete program, just a header, that I compile with the `g++` command given in the question. And the header don't compile. – Basile Starynkevitch Nov 20 '11 at 17:11
  • @BasileStarynkevitch: What is your `make()` function supposed to do? It seems to allocate memory for no reason and promptly lose the pointer to that allocated memory. – Mankarse Nov 20 '11 at 17:33

2 Answers2

4

Your problem is a multiple inheritance issue. Notice that the class IaItemValue inherits from both IaAnyValue and gc_cleanup (and IaDictionnaryItem inherits from IaItemValue), both of which provide overloads for operator new. In order to resolve this, you can add the following line to the class definition for IaDictionnaryItem:

using IaAnyValue::operator new;

chess007
  • 876
  • 6
  • 7
  • Out of curiosity, is there some syntax to invoke a particular case of `operator new` (with the construction step) by forcing it?? – Basile Starynkevitch Nov 20 '11 at 18:54
  • @BasileStarynkevitch: Yes there is: `IaAnyValue::operator new()`. Unfortunately this is not particularly useful, because there is no way to manually call the constructor for the allocated memory, and calls to `new` will always end up net being able to resolve the overloaded `operator new`s. Also note that the `BaseClass::functionName` syntax is available for things other than `operator new`. – Mankarse Nov 20 '11 at 18:56
2

In order to understand your problem, I've dug through your code and can make the following assertions:

  • IaAnyValue::allocate_new_value is a struct allocate_new_value_st {}
  • GCPlacement is an enum { NoGC, PointerFreeGC }

You have three defined new operators:

void* operator new(size_t);               
void* operator new(size_t, GCPlacement);  
void* operator new(size_t, void*);        

You need to be specific about what you call.

To call new(size_t):

new X;

To call new(size_t, GCPlacement):

new(NoGC) X;

To call new(size_t, void*):

allocate_new_value_st Y;
new(&Y) X;
netcoder
  • 66,435
  • 19
  • 125
  • 142
  • Thanks!! It is almost right, but I don't understand the last answer. I've created the empty `struct allocate_new_value_st` precisely to (artificially) be able to disambiguate. And I tried using `return new (UseGC) IaDictionnaryItem` and I am still getting the error... – Basile Starynkevitch Nov 20 '11 at 17:20
  • I edited my question to explain what I tried to follow your suggestion. I don't want `new (NoGC)` but `new (UseGC)` – Basile Starynkevitch Nov 20 '11 at 17:27