Подтвердить что ты не робот

Почему указание ссылки 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, становится лучшим кандидатом при разрешении перегрузки?

4b9b3361

Ответ 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:

  1. Для нестатических функций-членов тип неявного параметра объекта

- "ссылка lvalue на cv X" для функций, объявленных без ref-квалификатора или с рефлексификатором ref и

- "rvalue reference to cv X" для функций, объявленных с помощью && & реф-классификатор

(основное внимание).

Итак, я с ума сходил, почему разница в выходе. Без или с & спецификатор ref должен быть таким же, как здесь, правильно?

Ну, причина в дополнительном правиле, прокрашенном впоследствии в §13.3.1/5

Для нестатических функций-членов, объявленных без ref-квалификатора, применяется дополнительное правило:

- даже если параметр неявного объекта не является константным, значение rvalue может быть привязано к параметру, поскольку во всех других отношениях аргумент может быть преобразован в тип неявного параметра объекта.

Что в основном вызывает неконстантное значение rvalue для не-const lvalue преобразования и делает всю разницу в приведенном выше примере. D'э.