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

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

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

T instance = grabStuff<T>();

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


person lurscher    schedule 14.04.2012    source источник


Ответы (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, который возвращает ссылку на то, что вы в него передаете (и, таким образом, ответственность за предоставление допустимых входных данных лежит на вызывающем объекте).

person Kerrek SB    schedule 14.04.2012
comment
Объект не обязательно должен быть глобальным. Локальный объект, управляющий ресурсами, также является примером (я имею в виду, может быть: D). - person Nawaz; 14.04.2012
comment
@Kerrek, так вы говорите, что эту функцию следует вызывать только во временных? нельзя ли результат get() в вашем примере присвоить обычной ссылке Foo&? - person lurscher; 14.04.2012
comment
@Nawaz: Да, да, как я уже сказал, решать вам... Я просто хотел привести пример, который не std::move сам по себе. - person Kerrek SB; 14.04.2012
comment
@lurscher: Вы также можете привязать результат к ссылке: Foo && rr = get();. - person Kerrek SB; 14.04.2012

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

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

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

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

person Cosyn    schedule 15.04.2012

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

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

person Nawaz    schedule 14.04.2012
comment
std::move – это единственный значимый экземпляр типа возвращаемого значения rvalue-reference. Это никогда не будет иметь смысла в пользовательском коде. - person ildjarn; 14.04.2012
comment
@ildjarn: я не могу утверждать, что это никогда не будет иметь смысла в пользовательском коде. Я просто утверждаю, что rvalue-ссылка как тип возвращаемого значения может иметь смысл. - person Nawaz; 14.04.2012
comment
Я это утверждаю. ;-] В коде пользователя (если этот код пользователя не дублирует std::move по какой-то странной причине), возвращаемый тип ссылки rvalue не может делать ничего семантически значимого. - person ildjarn; 14.04.2012
comment
@ildjarn: еще слишком рано заявлять что-либо в этом роде; C++11 только что был выпущен, и в ближайшие 10 лет будет открыто много трюков и идиом. Так что скорее буду держать пальцы скрещенными. - person Nawaz; 14.04.2012
comment
Вы можете либо А) получить висячую ссылку, либо Б) подразумевать смену владельца, не гарантируя этого, что совершенно бесполезно. Вот и все. - person ildjarn; 14.04.2012