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

Что здесь означает один амперсанд?

Из ответа здесь.

class wrap {
public:
   operator obj() const & { ... }   //Copy from me.
   operator obj() && { ... }  //Move from me.
private:
   obj data_;
};

Я знаю, что && означает, что элемент будет вызываться, когда объект является ссылкой rvalue. Но что означает один амперсанд? Как это отличается от амперсанда?

4b9b3361

Ответ 1

Это означает, что элемент будет вызываться, когда объект является ссылкой lvalue.

[C++11: 9.3.1/5]: Нестатическая функция-член может быть объявлена ​​с помощью ref-qualifier (8.3.5); см. 13.3.1.

[C++11: 13.3.1/4]: Для нестатических функций-членов тип параметра неявного объекта

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

где X - это класс, членом которого является член, а cv - cv-квалификация в объявлении функции-члена. [..]

(и некоторые другие правила, которые я не могу найти)

Без реф-квалификатора функция всегда может вызываться независимо от категории значений выражения, через которое вы вызываете его:

struct foo
{
    void bar() {}
    void bar1() & {}
    void bar2() && {}
};

int main()
{
    foo().bar();  // (always fine)
    foo().bar1(); // doesn't compile because bar1() requires an lvalue
    foo().bar2();

    foo f;
    f.bar();      // (always fine)
    f.bar1();
    f.bar2();     // doesn't compile because bar2() requires an rvalue
}

Живая демонстрация (спасибо преторианцам)

Ответ 2

Но что означает один амперсанд?

Функция может быть вызвана только на lvalue, а не на rvalue.

Как это отличается от амперсанда?

Без ref-qualifier вы можете вызвать функцию на lvalue или rvalue.

С помощью ref-qualifier вы можете вызвать функцию только в соответствующей категории значений.

Ответ 3

Функция без ref-qualifier может быть вызвана как для rvalue, так и для lvalues. Функция с рефлексификатором && может быть вызвана только для rvalues. Функция с & ref-qualifier может быть вызвана только для lvalues.

class No { void foo(); };
class L { void foo() &; };
class R { void foo() &&; };

No().foo(); // valid
No no; no.foo(); // valid
L().foo(); // invalid
L l; l.foo(); // valid
R().foo(); // valid
R r; r.foo(); // invalid

К сожалению, я могу найти это правило только в 5.5/6, которое применяется только к выражениям разыменования с указателем на член. Я знаю, что это относится и к другим.

Кроме того, вы не можете перегружать ref-qualifier vs no ref-qualifier, см. 13.1/2 bullet 3. Вы можете перегрузить & vs &&.

(И благодаря моему бесплодному поиску стандарта, ответ LRiO теперь имеет всю эту информацию).