This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 119a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2025-12-20
[Voted into WP at October 2003 meeting.]
Consider this program:
struct S { static void f (int); void f (char); }; void g () { S::f ('a'); }G++ 3.1 rejects it, saying:
test.C:7: cannot call member function `void S::f(char)' without object
Mark Mitchell:It looks to me like G++ is correct, given 12.2.2.2.2 [over.call.func].This case is the "unqualified function call" case described in paragraph3 of that section. ("Unqualified" here means that there is no "x->" or"x." in front of the call, not that the name is unqualified.)
That paragraph says that you first do name lookup. It then asks youto look at what declaration is returned. (That's a bit confusing; youpresumably get a set of declarations. Or maybe not; the name lookupsection says that if name lookup finds a non-static member in a contextlike this the program is in error. But surely this program is noterroneous. Hmm.)
Anyhow, you have -- at least -- "S::f(char)" as the result of thelookup.
The keyword "this" is not in scope, so "all overloaded declarations ofthe function name in T become candidate functions and a contrived objectof type T becomes the implied object argument." That means we getboth versions of "f" at this point. Then, "the call is ill-formed,however, if overload resolution selects one of the non-static membersof T in this case." Since, in this case, "S::f(char)" is the winner,the program is ill-formed.
Steve Adamczyk:This result is surprising, because we've selected a functionthat we cannot call, when there is another function that can becalled. This should either be ambiguous, or it should select the staticmember function. See also 12.2.2 [over.match.funcs] paragraph 2:"Similarly, whenappropriate, the context can construct an argument list thatcontains an implied object argument..."
Notes from October 2002 meeting:
We agreed that g++ has it right, but the standard needs to be clearer.
Proposed resolution (October 2002, revised April 2003):
Change 12.2.2.2.2 [over.call.func] paragraphs 2 and 3 asfollows:
In qualified function calls, the name to be resolved is anid-expression and is preceded by an-> or.operator. Since the constructA->B is generally equivalentto(*A).B, the rest of Clause 12 [over]assumes, without loss of generality, that all member function calls have beennormalized to the form that uses an object and the. operator.Furthermore, Clause 12 [over]assumes that thepostfix-expression that is the leftoperand of the. operator has type ``cvT''whereT denotes a class.[Footnote: Note that cv-qualifiers on the type ofobjects are significant in overload resolution for both lvalue andclass rvalue objects. --- end footnote]Under this assumption, theid-expression in thecall is looked up as a member function ofT following the rules forlooking up names in classes (6.5.2 [class.member.lookup]).
If a member function is found, that function and its overloadeddeclarationsThe function declarations found by that lookupconstitute the set of candidate functions. The argument list is theexpression-list in the call augmented by the addition of theleft operand of the. operator in the normalized memberfunction call as the implied object argument (12.2.2 [over.match.funcs]).In unqualified function calls, the name isnot qualified by an-> or. operator and has the moregeneral form of aprimary-expression. The name is looked up in thecontext of the function call following the normal rules for name lookup infunction calls (
6.5.4 [basic.lookup.argdep]6.5 [basic.lookup]).If the name resolves to a non-member function declaration, thatfunction and its overloaded declarationsThe function declarations found by that lookupconstitute the set of candidate functions.[Footnote: Because of the usual name hiding rules,these will be introduced by declarations or byusing-directives allfound in the same block or all found at namespace scope. --- end footnote]Because of the rules for name lookup,the set of candidate functions consists (1) entirely of non-member functionsor (2) entirely of member functions of some classT. Incase (1), tThe argument list is the same astheexpression-list in the call.If the name resolves to a nonstatic member function, then thefunction call is actually a member function call.In case (2), the argument list is theexpression-list in thecall augmented by the addition of an implied object argument as ina qualified function call.If the keywordthis (_N4868_.11.4.3.2 [class.this])is in scope and refers totheclassTof that memberfunction, or a derived classthereofofT, thenthefunction call is transformed into a normalized qualifiedfunction call usingimplied object argument is(*this)as thepostfix-expressionto the left of the. operator.The candidatefunctions and argument list are as described for qualified function callsabove.If the keywordthis is not in scope or refers toanother class, thenname resolution found a static member of someclassT.In this case,all overloaded declarations of the function name inT become candidate functions anda contrived object oftypeT becomes the implied object argument.[Footnote: An implied object argument must becontrived to correspond to the implicit object parameter attributed to memberfunctions during overload resolution. It is not used in the call to theselected function. Since the member functions all have the same implicitobjectparameter, the contrived object will not be the cause to select or reject afunction. --- end footnote]If the argument list is augmented by a contrived objectandThe call is ill-formed, however, ifoverloadresolution selects one of the non-static member functions ofT, thecall is ill-formedin this case.
Note thatissue 239 also editsparagraph 3.