Date: Wed, 28 Dec 2022 10:54:27 -0500

On Wed, Dec 28, 2022 at 7:14 AM Lénárd Szolnoki via Std-Discussion

<std-discussion_at_[hidden]> wrote:

> I don't think you get an automatic operator& that is accessible with

> the .operator&() syntax. `&u` and `&move(u)` is differrent.

Indeed. The syntax E.operator@() can only resolve to member functions

of E's class. The only implicitly-declared member functions are the

copy assignment operator, the move assignment operator, and the

operator== function implicitly declared for each operator<=> function

defined as defaulted (11.10.1 [class.compare.default] para. 4). But

ordinary operator expressions are subject to overload resolution which

includes built-in candidates and rewritten candidates.

To expand on the difference between &d and &move(d) which makes only

the former valid:

Dog::operator& is not a viable function for &d, since there is no

implicit conversion sequence which converts lvalue d to type const

volatile Dog&&. Since there are no viable functions, 12.2.2.3

[over.match.oper] paragraph 13 applies: "If the operator is the

operator ,, the unary operator &, or the operator ->, and there are no

viable functions, then the operator is assumed to be the built-in

operator and interpreted according to 7.6." Therefore, &d is

interpreted as the built-in & operator.

Meanwhile, Dog::operator& is a viable function for &move(d), since a

reference of type const volatile Dog&& can bind directly to xvalue

move(d). Therefore, overload resolution selects Dog::operator& for

&move(d), resulting in an error, since the function is defined as

deleted.

<std-discussion_at_[hidden]> wrote:

> I don't think you get an automatic operator& that is accessible with

> the .operator&() syntax. `&u` and `&move(u)` is differrent.

Indeed. The syntax E.operator@() can only resolve to member functions

of E's class. The only implicitly-declared member functions are the

copy assignment operator, the move assignment operator, and the

operator== function implicitly declared for each operator<=> function

defined as defaulted (11.10.1 [class.compare.default] para. 4). But

ordinary operator expressions are subject to overload resolution which

includes built-in candidates and rewritten candidates.

To expand on the difference between &d and &move(d) which makes only

the former valid:

Dog::operator& is not a viable function for &d, since there is no

implicit conversion sequence which converts lvalue d to type const

volatile Dog&&. Since there are no viable functions, 12.2.2.3

[over.match.oper] paragraph 13 applies: "If the operator is the

operator ,, the unary operator &, or the operator ->, and there are no

viable functions, then the operator is assumed to be the built-in

operator and interpreted according to 7.6." Therefore, &d is

interpreted as the built-in & operator.

Meanwhile, Dog::operator& is a viable function for &move(d), since a

reference of type const volatile Dog&& can bind directly to xvalue

move(d). Therefore, overload resolution selects Dog::operator& for

&move(d), resulting in an error, since the function is defined as

deleted.

Received on 2022-12-28 15:54:39