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
Do we really need the & ref-qualifier? We could get the same behavior without it if we relaxed the restriction on ref-qualified and non-ref-qualified overloads in the same set:
with the & ref-qualifier | without the & ref-qualifier |
struct S { void f(); }; |
struct S { void f(); }; |
struct S { void f() &; }; |
struct S { void f(); void f() && = delete; }; |
struct S { void f() &&; }; |
struct S { void f() &&; }; |
struct S { void f() &; void f() &&; }; |
struct S { void f(); void f() &&; }; |
The main objection I can see to this change is that we would lose the notational convenience of the & ref-qualifier, which would need to be replaced by a pair of declarations. We might overcome this by still allowing a single & on a function (although it would not be a ref-qualifier) as a synonym to a non-ref-qualified declaration plus a deleted ref-qualified declaration.
The biggest asymmetry between the implicit object parameter and regular parameters is not in reference binding but in type deduction. Consider:
template <class R, class C, class A> void f(R (C::*p)(A));
With these members:
struct S { void mv(std::string); void mr(std::string&); void ml(std::string&&); };
then
f(&S::mv); // deduces A = string f(&S::mr); // deduces A = string& f(&S::ml); // deduces A = string&&
On the other hand, with these members:
struct S { void mv(std::string); void mr(std::string) &; void ml(std::string) && };
then
f(&S::mv); // deduces C = S f(&S::mr); // illegal f(&S::ml); // illegal
To make template f work with any pointer to member function, I need three overloads of f. Add cv-qualifiers and it's twelve overloads!
And then there is the interaction with concepts. Consider this type:
struct Value { Value& operator=(const Value&) &; };
Is it, say, Regular? If so, will the following compile, and what is the outcome?
template <Regular T> void f() { T() = T(); } void g() { f<Value>(); }
If Value is not Regular, that is a good motivation to avoid ever using & ref-qualifiers on operator= (and probably on any member functions).
If Value is Regular, then either f<Value>() doesn't compile, violating one of the principal motivations for concepts, or it calls Value::operator= on an rvalue, which was explicitly prohibited.
Rationale, March, 2009:
The CWG did not feel that the suggested change was a signficant improvement over the existing specification.