Есть ли какая-то польза от ссылок на const? - PullRequest
69 голосов
/ 09 февраля 2011

Наверное, нет, но я хотел бы подтвердить.Можно ли использовать const Foo&&, где Foo - это тип класса?

Ответы [ 4 ]

67 голосов
/ 09 февраля 2011

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

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

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

Обновление

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

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

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

template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;
4 голосов
/ 09 февраля 2011

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

1 голос
/ 03 мая 2019

Помимо std :: ref , стандартная библиотека также использует ссылку const rvalue в 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-квалифицированные функции. Тем не менее, я не знаю использования для const rvalue ref квалифицированных функций.

1 голос
/ 09 февраля 2011

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

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, чтобы он не мог вызываться для lvalue без изменения значения rvalue (как в слишком простом примере выше).

...