Date: Thu, 13 Jul 2023 10:04:36 +0000
Per [dcl.fct.def.default], a program is ill-formed if the return type of an explicitly defaulted assignment operator does not match that of the implicitly declared operator, and per [class.copy.assign], the return type for that implicitly declared copy or move assignment operator of class X must be of type X&, which by transitive property means that the program is ill-formed if the return type of an explicitly defaulted assignment operator for class X is not X&. We can therefore say that the compiler "knows" exactly what return type such a function must have with no ambiguity.
I propose allowing auto& (and only auto& as an explicit reference) in place of X& for the return type, where returning auto& will be equivalent to returning X&. The motivation here is consistency. As far as I can see, explicitly defaulted assignment operators are about the only member functions you are likely to write which explicitly cannot deduce their return type. This seems stylistically inconsistent when writing code where every other function within a class is perfectly happy to return some auto variant and deduce its type, particularly when you already know exactly what type must be returned by the function in all cases. Indeed, the standard does not appear to impose any particular restriction on the return type of explicitly deleted functions (including special member functions), so it really is just explicitly defaulted assignment operators which seem to be the odd ones out.
As far as I can tell the historical reasoning behind this not being added around C++11 was that auto return deduces the type from the actual return statement in the function body, and since an explicitly defaulted function has no body, this is not possible. However, since C++20 the three-way comparison operator is permitted to have auto as its return type when explicitly defaulted, which suggests that the old reasoning is flexible to change.
I was considering proposing to allow decltype(auto) in such situations too, since it is so strongly associated with returning references. However, from my testing to compare it for consistency with operator<=>, it seems that compilers currently disagree on whether returning decltype(auto) is permitted, and I would not want to add more confusion if there already is any. Either way, I'd be interested in hearing the opinions of the community on that idea.
I hope I've been clear, but if in case I have not, here is how it looks in code:
struct Defaulted{
//Allowed
Defaulted& operator=(const Defaulted&) = default;
//Allowed
auto operator=(const Defaulted&) -> Defaulted& = default;
//Forbidden: Proposed to allow, equivalent to returning Defaulted& explicitly.
auto& operator=(const Defaulted&) = default;
};
With a fuller example of some things which I've touched on here: https://godbolt.org/z/qKK93qqPM
I know this is only a minor change for code style purposes; and one which would likely only change a small amount of wording to allow this specific case. But while I can't speak for anyone else it seems inconsistent to me that these special member functions cannot deduce their return type when almost every other function can, and when only one specific return type is permitted anyway. I'd be interested in hearing what the community has to say on this proposal.
I propose allowing auto& (and only auto& as an explicit reference) in place of X& for the return type, where returning auto& will be equivalent to returning X&. The motivation here is consistency. As far as I can see, explicitly defaulted assignment operators are about the only member functions you are likely to write which explicitly cannot deduce their return type. This seems stylistically inconsistent when writing code where every other function within a class is perfectly happy to return some auto variant and deduce its type, particularly when you already know exactly what type must be returned by the function in all cases. Indeed, the standard does not appear to impose any particular restriction on the return type of explicitly deleted functions (including special member functions), so it really is just explicitly defaulted assignment operators which seem to be the odd ones out.
As far as I can tell the historical reasoning behind this not being added around C++11 was that auto return deduces the type from the actual return statement in the function body, and since an explicitly defaulted function has no body, this is not possible. However, since C++20 the three-way comparison operator is permitted to have auto as its return type when explicitly defaulted, which suggests that the old reasoning is flexible to change.
I was considering proposing to allow decltype(auto) in such situations too, since it is so strongly associated with returning references. However, from my testing to compare it for consistency with operator<=>, it seems that compilers currently disagree on whether returning decltype(auto) is permitted, and I would not want to add more confusion if there already is any. Either way, I'd be interested in hearing the opinions of the community on that idea.
I hope I've been clear, but if in case I have not, here is how it looks in code:
struct Defaulted{
//Allowed
Defaulted& operator=(const Defaulted&) = default;
//Allowed
auto operator=(const Defaulted&) -> Defaulted& = default;
//Forbidden: Proposed to allow, equivalent to returning Defaulted& explicitly.
auto& operator=(const Defaulted&) = default;
};
With a fuller example of some things which I've touched on here: https://godbolt.org/z/qKK93qqPM
I know this is only a minor change for code style purposes; and one which would likely only change a small amount of wording to allow this specific case. But while I can't speak for anyone else it seems inconsistent to me that these special member functions cannot deduce their return type when almost every other function can, and when only one specific return type is permitted anyway. I'd be interested in hearing what the community has to say on this proposal.
Received on 2023-07-13 10:04:38