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

Нужны ли ссылки rvalue на const?

Я думаю, нет, но я хотел бы подтвердить. Используется ли для const Foo&&, где Foo - тип класса?

4b9b3361

Ответ 1

Они иногда полезны. Сам проект С++ 0x использует их в нескольких местах, например:

template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;

Вышеуказанные две перегрузки гарантируют, что другие функции ref(T&) и cref(const T&) не свяжутся с rvalues ​​(что в противном случае было бы возможно).

Обновление

Я только что проверил официальный стандарт N3290, который, к сожалению, не является общедоступным, и имеет в 20.8 функциональных объектов [ function.objects]/p2:

template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;

Затем я проверил самый последний проект пост-С++ 11, который является общедоступным, N3485, а в 20.8 Объекты функции [function.objects]/p2 он все еще говорит:

template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;

Ответ 2

Они разрешены и даже функции ранжируются на основе const, но поскольку вы не можете перемещаться из объекта const, указанного const Foo&&, они не являются полезными.

Ответ 3

Я не могу думать о ситуации, когда это было бы полезно непосредственно, но оно может использоваться косвенно:

template<class T>
void f(T const &x) {
  cout << "lvalue";
}
template<class T>
void f(T &&x) {
  cout << "rvalue";
}

template<class T>
void g(T &x) {
  f(T());
}

template<class T>
void h(T const &x) {
  g(x);
}

T в g является T const, поэтому f x является T const & &.

Вероятно, это приводит к ошибке компиляции в f (когда она пытается переместить или использовать объект), но f может принять rvalue-ref, чтобы его нельзя было вызывать на lvalues, не изменяя значение rvalue (как в слишком простой пример выше).

Ответ 4

Помимо std :: ref, стандартная библиотека также использует ссылку на константное значение в std :: as_const для той же цели.

template <class T>
void as_const(const T&&) = delete;

Он также используется как возвращаемое значение в std :: необязательный при получении обернутого значения:

constexpr const T&& operator*() const&&;
constexpr const T&& value() const &&;

Как и в std :: get:

template <class T, class... Types>
constexpr const T&& get(const std::variant<Types...>&& v);
template< class T, class... Types >
constexpr const T&& get(const tuple<Types...>&& t) noexcept;

Предположительно это делается для того, чтобы поддерживать категорию значения, а также постоянство оболочки при доступе к перенесенному значению.

Это делает различие в том, можно ли вызывать постоянные ref-квалифицированные функции для обернутого объекта. Тем не менее, я не знаю использования для conts rvalue ref квалифицированных функций.