семантика возвращаемого типа ссылки r-value?

представляет ли такой возвращаемый тип что-то значимое в c++11?

template <typename R>
R&& grabStuff();

T instance = grabStuff<T>();

Я надеюсь, что grabStuff должен выдать ошибку времени компиляции, если R не имеет конструктора перемещения, так как это, похоже, запрещает возвращаемому типу использовать конструктор копирования

3 ответов


Как всегда, при возврате ссылок вы должны вернуть ссылку на то, что все еще живо после возвращения функции. Как вы это сделаете, зависит от вас. Пример:

T global_thing;

T && get() { return std::move(global_thing); }

struct Foo { Foo(T &&); /* ... */ };

int main()
{
    global_thing.reset();
    Foo a(get());
    global_thing.reset();
    Foo b(get());
}

более типичным примером возврата ссылки rvalue является std::move сам, однако, который возвращает ссылку на вещь, которую вы передаете на it (и, таким образом, это ответственность вызывающего абонента за предоставление действительного ввода).


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

В самом деле std::move тип возврата T&& (ссылка rvalue), которая имеет смысл, поскольку она определяет саму цель существования std::move в библиотеке C++11:


Если возвращаемый тип функции является ссылкой rvalue, то результатом вызова функции является xvalue; если возвращаемый тип не является ссылкой, то результатом вызова функции является prvalue.

и xvalue и prvalue являются rvalues, между ними есть некоторые незначительные различия, больше похожие на различия между ссылкой и не ссылкой. Например, xvalue может иметь неполный тип, в то время как prvalue обычно имеет полный тип или тип void. Когда ИД типа применяется к xvalue, тип которого является полиморфным типом класса, результат относится к динамическому типу; а для prvalue результат относится к статическому типу.

для вашего заявления объявления T instance = grabStuff<T>();, Если T-тип класса, я думаю, что в этом контексте нет разницы между xvalue и prvalue.

инициализатор является rvalue, поэтому компилятор предпочитает конструктор перемещения. Но если конструктор перемещения не объявлен, а конструктор копирования с параметром ссылки const объявляется, то этот конструктор копирования будет выбран, и ошибки нет. Я не знаю, почему ты хочешь, чтобы это было ошибкой. Если это ошибка, любой старый код будет неправильным при копировании-инициализации некоторого объекта из rvalue.