Почему указание ссылки lvalue для * этого в функции-член отличается от того, что не указывает ничего?
Рассмотрим этот код:
#include <iostream>
using namespace std;
struct A {
void f() { cout << "A::f" << endl; }
void f() const { cout << "A::f const" << endl; }
};
struct B {
void f() & { cout << "B::f &" << endl; }
void f() const & { cout << "B::f const &" << endl; }
};
A getA() { return A{}; }
B getB() { return B{}; }
int main() {
getA().f();
getB().f();
}
который печатает
A::f
B::f const &
Для B
выбирается перегрузка const, а не константа. Я предполагаю, что это означает, что указание lvalue ref refifier для * это отличается от того, что вообще не указывается. Почему это? Изменяется ли тип изменения "неявный этот аргумент" и перегрузка const, становится лучшим кандидатом при разрешении перегрузки?
Ответы
Ответ 1
В этом случае:
struct A {
void f() { cout << "A::f" << endl; }
void f() const { cout << "A::f const" << endl; }
};
getA().f();
Обе перегрузки жизнеспособны для f
, но не константа одна предпочтительна, потому что она не требует преобразования.
Но в этом случае:
struct B {
void f() & { cout << "B::f &" << endl; }
void f() const & { cout << "B::f const &" << endl; }
};
getB().f();
Первая перегрузка требует this
как lvalue. Но в getB().f()
результат getB()
является значением prvalue, которое не может связываться с не-const lvalue. Таким образом, эта перегрузка не является жизнеспособной и не выбрана.
Вторая перегрузка, однако, требует this
как const lvalue, с которым может связываться prvalue: эта перегрузка жизнеспособна и выбрана компилятором.
Ответ 2
Для справки предложение, которое меня полностью ввели, находится в [over.match.funcs]
, §13.3.1/4 из N3337:
- Для нестатических функций-членов тип неявного параметра объекта
- "ссылка lvalue на cv X" для функций, объявленных без ref-квалификатора или с рефлексификатором ref и
- "rvalue reference to cv X" для функций, объявленных с помощью && & реф-классификатор
(основное внимание).
Итак, я с ума сходил, почему разница в выходе. Без или с &
спецификатор ref должен быть таким же, как здесь, правильно?
Ну, причина в дополнительном правиле, прокрашенном впоследствии в §13.3.1/5
Для нестатических функций-членов, объявленных без ref-квалификатора, применяется дополнительное правило:
- даже если параметр неявного объекта не является константным, значение rvalue может быть привязано к параметру, поскольку во всех других отношениях аргумент может быть преобразован в тип неявного параметра объекта.
Что в основном вызывает неконстантное значение rvalue для не-const lvalue преобразования и делает всю разницу в приведенном выше примере. D'э.