"We do not use const rvalue references" Really?
В заголовке цитата из B.Stroustrup "The C++ Programming Language" (Fourth edition) (7.7.2 Rvalue References)
Посмотрим, как это выглядит в действительности.
Если заглянуть в драфт последнего стандарта, в раздел 7.3.1 Преобразование lvalue-to-rvalue
то мы увидим следующее:
Что значит "cv-unqualified"? Опять посмотрим в стандарте:
Посмотрим, как это выглядит в действительности.
Если заглянуть в драфт последнего стандарта, в раздел 7.3.1 Преобразование lvalue-to-rvalue
то мы увидим следующее:
A glvalue ([basic.lval]) of a non-function, non-array type T can be converted to a prvalue.[...]
If T is a non-class type, the type of the prvalue is the cv-unqualified version of T. Otherwise, the type of the prvalue is T.Что значит "cv-unqualified"? Опять посмотрим в стандарте:
Each type which is a cv-unqualified complete or incomplete object type or is void ([basic.types]) has three corresponding cv-qualified versions of its type: a const-qualified version, a volatile-qualified version, and a const-volatile-qualified version.
[...]
The cv-qualified or cv-unqualified versions of a type are distinct types; however, they shall have the same representation and alignment requirements.
Итак, вернемся к rvalue. Да, в С rvalue никогда не имели cv-квалификаторов. Только lvalue. С другой стороны, rvalue для классов могут иметь cv-квалификаторы, а встроенные типы (подобные int) не могут. Посмотрим пример
class A {
public:
void foo() const { std::cout << "A::foo() const\n"; }
void foo() { std::cout << "A::foo()\n"; }
};
A bar() { return A(); }
const A cbar() { return A(); }
int main()
{
bar().foo(); // calls foo
cbar().foo(); // calls foo const
}
Функция bar() возвращает rvalue на А, а функция cbar() возвращает const rvalue на А. Этот факт подтверждается вызовом соответственно неконстантной и константной версий функции foo().
Программа выводит
A::foo() A::foo() const
При отсутствии константной версии foo() мы получаем ошибку при компиляции (GCC 8.2.0):
prog.cc: In function 'int main()':
prog.cc:16:16: error: passing 'const A' as 'this' argument discards qualifiers [-fpermissive]
cbar().foo(); // calls foo const
^
prog.cc:6:10: note: in call to 'void A::foo()'
void foo() { std::cout << "A::foo()\n"; }
После изменения примера для возврата rvalue на примитивный тип
#include <iostream>
int bar() { return int(); }
const int cbar() { return int(); }
int main()
{
bar();
cbar();
}
получаем предупреждение компилятора
prog.cc:4:1: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
const int cbar() { return int(); }
^~~~~
Использована статья Eli Bendersky
Комментарии
Отправить комментарий