This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-12-19
[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 paragraph 3 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 you to look at what declaration is returned. (That's a bit confusing; you presumably get a set of declarations. Or maybe not; the name lookup section says that if name lookup finds a non-static member in a context like this the program is in error. But surely this program is not erroneous. Hmm.)
Anyhow, you have -- at least -- "S::f(char)" as the result of the lookup.
The keyword "this" is not in scope, so "all overloaded declarations of the function name in T become candidate functions and a contrived object of type T becomes the implied object argument." That means we get both versions of "f" at this point. Then, "the call is ill-formed, however, if overload resolution selects one of the non-static members of 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 function that we cannot call, when there is another function that can be called. This should either be ambiguous, or it should select the static member function. See also 12.2.2 [over.match.funcs] paragraph 2: "Similarly, when appropriate, the context can construct an argument list that contains 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 as follows:
In qualified function calls, the name to be resolved is an id-expression and is preceded by an -> or . operator. Since the construct A->B is generally equivalent to (*A).B, the rest of Clause 12 [over] assumes, without loss of generality, that all member function calls have been normalized to the form that uses an object and the . operator. Furthermore, Clause 12 [over] assumes that the postfix-expression that is the left operand of the . operator has type ``cv T'' where T denotes a class. [Footnote: Note that cv-qualifiers on the type of objects are significant in overload resolution for both lvalue and class rvalue objects. --- end footnote] Under this assumption, the id-expression in the call is looked up as a member function of T following the rules for looking up names in classes (6.5.2 [class.member.lookup]).
If a member function is found, that function and its overloaded declarationsThe function declarations found by that lookup constitute the set of candidate functions. The argument list is the expression-list in the call augmented by the addition of the left operand of the . operator in the normalized member function call as the implied object argument (12.2.2 [over.match.funcs]).In unqualified function calls, the name is not qualified by an -> or . operator and has the more general form of a primary-expression. The name is looked up in the context of the function call following the normal rules for name lookup in function calls (
6.5.4 [basic.lookup.argdep]6.5 [basic.lookup]).If the name resolves to a non-member function declaration, that function and its overloaded declarationsThe function declarations found by that lookup constitute the set of candidate functions.[Footnote: Because of the usual name hiding rules, these will be introduced by declarations or by using-directives all found 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 functions or (2) entirely of member functions of some class T. In case (1), tThe argument list is the same as the expression-list in the call.If the name resolves to a nonstatic member function, then the function call is actually a member function call.In case (2), the argument list is the expression-list in the call augmented by the addition of an implied object argument as in a qualified function call. If the keyword this (_N4868_.11.4.3.2 [class.this]) is in scope and refers totheclass Tof that member function, or a derived classthereofof T, then thefunction call is transformed into a normalized qualified function call usingimplied object argument is(*this)as the postfix-expression to the left of the . operator.The candidate functions and argument list are as described for qualified function calls above.If the keyword this is not in scope or refers to another class, thenname resolution found a static member of some classT. In this case,all overloaded declarations of the function name in T become candidate functions anda contrived object of type T becomes the implied object argument. [Footnote: An implied object argument must be contrived to correspond to the implicit object parameter attributed to member functions during overload resolution. It is not used in the call to the selected function. Since the member functions all have the same implicit object parameter, the contrived object will not be the cause to select or reject a function. --- end footnote] If the argument list is augmented by a contrived object andThe call is ill-formed, however, ifoverload resolution selects one of the non-static member functions of T, the call is ill-formedin this case.
Note that issue 239 also edits paragraph 3.