Что здесь означает один амперсанд?
Из ответа здесь.
class wrap {
public:
operator obj() const & { ... } //Copy from me.
operator obj() && { ... } //Move from me.
private:
obj data_;
};
Я знаю, что &&
означает, что элемент будет вызываться, когда объект является ссылкой rvalue. Но что означает один амперсанд? Как это отличается от амперсанда?
Ответы
Ответ 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 теперь имеет всю эту информацию).