Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!brl-adm!rutgers!princeton!allegra!alice!bs From: bs@alice.UUCP Newsgroups: comp.lang.c++ Subject: Re: Address of overloaded member fn.? Message-ID: <6437@alice.uUCp> Date: Sun, 7-Dec-86 22:14:35 EST Article-I.D.: alice.6437 Posted: Sun Dec 7 22:14:35 1986 Date-Received: Mon, 8-Dec-86 03:26:31 EST References: <165700001@uiucdcsb> Organization: AT&T Bell Laboratories, Murray Hill NJ Lines: 132 Summary: There is a bug, but you can manage anyhow Kevin Kenny writes > Is there any way, in current C++, to take the address of an overloaded > member function. I understand that the compiler will be able to > determine the type of (&cl::entrypoint) by the type of the receiving > pointer in an assignment statement, but there doesn't seem to be any > way to do it at present. There appears to be a bug. Sorry. However, the program below is not legal C++: > The closest I came was: > ------------------------------------------------------------------------ > class testclass { > public: > testclass& operator- (); > testclass& operator- (testclass); > testclass (); > }; > > typedef testclass& (*NILADIC) (void*); > typedef testclass& (*MONADIC) (void*, testclass); > typedef testclass& (*CONSTRUCTOR) (); > > main () { > NILADIC niladic = &testclass :: operator-; > MONADIC monadic = &testclass :: operator-; > CONSTRUCTOR constructor = &testclass :: testclass; > } > ------------------------------------------------------------------------ > which gives the following: > ------------------------------------------------------------------------ > "memptrtest.c", line 16: error: cannot deduce type for &overloaded _minus() > "memptrtest.c", line 16: sorry, <> cannot recover from earlier errors > ------------------------------------------------------------------------ > and I don't see any obvious way to disambiguate the overloaded > operator. The problem here is that the testclass defines a unary and a binary minus (not a NILADIC and MONADIC). Remember the implicit argument ``this''. You cannot take a pointer to a member function and stuff it into a plain pointer to function and expect it to work. The correct way of taking the pointers is: class testclass { public: testclass& operator- (); // unary testclass& operator- (testclass); // binary testclass (); }; typedef testclass& (testclass::* UMEM) (); typedef testclass& (testclass::* BMEM) (testclass); main () { UMEM unary = &testclass :: operator-; // testclass::operator-() BMEM binary = &testclass :: operator-; // testclass::operator-(testclass) } Unfortunately, that doesn't work either! It ought to. It will be fixed (but I cannot promise when). > Any ideas? I could kludge around it by making a named function that > in turn calls the operator, but that's even uglier than the usual > pointer-to-entry-function kludge (plus, it hasn't been blessed by Mr > Stroustrup). Yes. The problem is not that the functions involved are operator functions (the problem persists when you rename testclass::operator- to testclass::minus) but that there is a bug in the resolution of pointers to overloaded members. However, the problem can be bypassed by having ``-'' implemented by a friend rather than a member (that is what I usually do - I suppose that is why I did not find the bug): class testclass { public: friend testclass& operator- (testclass); // unary friend testclass& operator- (testclass,testclass); // binary testclass (); }; typedef testclass& (*UNARY) (testclass); typedef testclass& (*BINARY) (testclass,testclass); main () { UNARY unary = &operator-; // operator-(testclass) BINARY binary = &operator-; // operator-(testclass,testclass) } I prefer this solution because if there is a conversion to testclass, say testclass::testclass(int) then it can be applied to a first operand of - as well as the second. Since such a conversion typically ought not be applied in the case of a unary - the unary operator- ought to be a member. Thus the ``ideal'' solution will in many cases be: class testclass { public: testclass& operator- (); // unary friend testclass& operator- (testclass,testclass); // binary testclass (int); }; typedef testclass& (testclass::* UNARY) (); typedef testclass& (*BINARY) (testclass,testclass); main () { UNARY unary = &testclass::operator-; // operator-(testclass) BINARY binary = &operator-; // operator-(testclass,testclass) } As it happens, this too works. PS. The really crude brute force approach also works: class testclass { public: testclass& operator- (); testclass& operator- (testclass); testclass (); }; typedef testclass& (*NILADIC) (void*); typedef testclass& (*MONADIC) (void*, testclass); main () { testclass a; NILADIC niladic = (NILADIC)&a.operator-; MONADIC monadic = (MONADIC)&a.operator-; } Avoid it if you can.