cplusplus / CWG

Core Working Group
24 stars 7 forks source link

[expr.prim.id] An id-expression that denotes an overload set shouldn't be a specific function #359

Open xmh0511 opened 1 year ago

xmh0511 commented 1 year ago

Full name of submitter (unless configured in github; will be published with the issue): Jim X

[expr.prim.id.unqual] p3 and [expr.prim.id.qual] p5 says:

The result is the entity denoted by the unqualified-id ([basic.lookup.unqual]).

an lvalue if the entity is a function

The result of a qualified-id Q is the entity it denotes ([basic.lookup.qual]). ... The result is an lvalue if the member is

  • [...]

However, [basic.lookup.general] p1 says:

If the declarations found by name lookup all denote functions or function templates, the declarations are said to form an overload set.

That is, an id-expression for which the name lookup finds only functions or function templates denotes an overload set, instead of denoting a specific function or function template.

Say an expression is a lvalue means it denotes a specific function, as per [basic.lval] p1

A glvalue is an expression whose evaluation determines the identity of an object or function.

In other words, an id-expression that denotes an overload set cannot be identified to a specific function without any further context(i.e. overload resolution for a function call or taking the address). This opinion is proved by [over.over] p1

An id-expression whose terminal name refers to an overload set S

Suggested Resolution

An id-expression, after undergoing name lookup, that denotes all functions or function templates is an overload set, which does not denote any specific function, so, it's too early to say the id-expression is a lvalue or something else that has an identity. Such an id-expression denotes a specific function only after overload resolution for it according to the context.

Moreover, the current standard lacks a reference to associates [over.over] with [expr.unary.op] p3, the explicit introduction of overload resolution only appears in [dcl.init.general]. In summary, it lacks an introduction in subclauses in [expr] to specify how overload resolution will apply to resolve the id-expression that denotes an overload set.

jensmaurer commented 1 year ago

I think there is no question what we mean here, so the remaining issue is what is the minimum change that makes the words (formally) right.

Maybe we want to say that a glvalue can also denote an overload set. Then we fix expr.prim.id.* to refer to "overload set", not to "function" (overload resolution has not happened at that stage, yet). And we add a cross-reference to over.over in expr.unary.op p3.

Or we define another expression category "overload set" in addition to prvalue, lvalue, xvalue.

xmh0511 commented 1 year ago

@jensmaurer IIUC, I think [expr.ref] p6.3 has already used the first option

If E2 is an overload set, function overload resolution ([over.match]) is used to select the function to which E2 refers. The type of E1.E2 is the type of E2 and E1.E2 refers to the function referred to by E2.

So, an id-expression, for which the name lookup finds the overload set, just denotes an overload set, whether it further denotes a glvalue or prvalue is determined by the result of the overload resolution according to the context.

jensmaurer commented 1 year ago

Since overload sets will either be eventually ill-formed or they denote a (unique) function, the option "prvalue" isn't.

xmh0511 commented 1 year ago

However, [expr.ref] p6.3 does mean that the prvalue is determined after overload resolution. Incidentally, why does Class::non_static_member_function or obj.non_static_member_function need to be prvalue? As defined in expr.prim.id.qual#5

The result is an lvalue if the member is

  • a function other than a non-static member function,
  • a non-static member function if Q is the operand of a unary & operator,

How will it be harmful if Q which is a non-static member function is always a lvalue(after overload resolution)?

jensmaurer commented 1 year ago

Ah, right.

I think it was a coin toss that came out this way.

xmh0511 commented 1 year ago

@jensmaurer See the updated part in the above comment, I didn't see the harm if we say Class::non_static_member_function and obj.non_static_member_function is a glvalue after overload resolution. Why it should be a prvalue, as specified in expr.ref#6.3.2 and expr.prim.id.qual#5.1.

expr.prim.id.qual#5.1 even is a bit contradictory with expr.prim.id.qual#5.2