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

С++ 0x const RValue ссылка как параметр функции

Я пытаюсь понять, почему кто-то напишет функцию, которая принимает ссылку const rvalue.

В приведенном ниже примере кода, какая цель - опорная функция const rvalue (возврат "3" ). И почему предпочтение разрешение перегрузки сопзЬ Rvalue выше Const-значение опорной функции (возвращение "2" ).

#include <string>
#include <vector>
#include <iostream>

std::vector<std::string> createVector() { return std::vector<std::string>(); } 

//takes movable rvalue
void func(std::vector<std::string> &&p) { std::cout << "1"; }

//takes const lvalue
void func(const std::vector<std::string> &p)  { std::cout << "2"; }

//takes const rvalue???
//what is the point of const rvalue? if const I assume it is not movable?
void func(const std::vector<std::string> &&p) { std::cout << "3"; }

int main()
{
    func(createVector());
    return 0;
}
4b9b3361

Ответ 1

Lvalues ​​настоятельно предпочитают привязку к ссылкам lvalue, и аналогичные ссылки rvalue сильно предпочитают связывание с ссылками rvalue. Модифицируемые выражения слабо предпочитают связывание с неконстантной ссылкой.

Итак, когда ваш компилятор делает разрешение перегрузки, он проверяет, есть ли перегрузка, которая принимает ссылку rvalue, потому что это очень сильно. В этом случае, поскольку разложение является изменяемым значением r, поэтому выигрывает эталонная перегрузка rvalue.

Фактически используется для ссылок const rvalue, их можно использовать, чтобы убедиться, что что-то не привязывает к rvalue. Помните, что rvalue связывается с константой lvalue, поэтому, если вы это сделали:

template <typename T> void foo(const T& bar) { /* ... */ }

И вызывается функция с помощью:

foo(createVector());

Все будет хорошо. Однако иногда желательно обеспечить, чтобы вы могли передавать только lvalues ​​функции (это имеет место для std::ref для одного). Вы можете добиться этого, добавив перегрузку:

template <typename T> void foo(const T&&) = delete;

Помните, что rvalues ​​сильно предпочитают привязку к rvalue-ссылкам, а модифицируемые выражения предпочитают слабое связывание с неконстантными ссылками. Поскольку у нас есть константа rvalue-reference, это в основном означает, что каждое одно rvalue будет связываться с этим, поэтому, если вы попытаетесь передать rvalue на foo(), ваш компилятор даст ошибку. Это единственный способ достичь такой функциональности и, следовательно, иногда полезен.

Ответ 2

Разрешение перегрузки предпочитает const rvalue над const lvalue, потому что, ну, это rvalue, и вы привязываете его к ссылке rvalue, но вам нужно добавить const в обоих случаях, поэтому определенную ссылку rvalue предпочтительнее.

Такие вещи обычно бессмысленны - лучше оставить их привязанными к перегрузкам const lvalue. const rvalues ​​не имеют реального использования.