2015-11-30 2 views
8

Он пришел к моему вниманию, что std::forward бесполезно в этом контексте:Почему станд :: вперед бесполезно в этом контексте

void consumeObject(std::unique_ptr<Object>&& robj) { 
    myvector.emplace_back(std::forward<std::unique_ptr<Object>>(robj)); 
} 

Почему? Я думал, что к тому моменту, когда ссылка rvalue связывается с параметром функции (т. Е. Я могу ссылаться на нее по имени), она становится lvalue в этой области и для того, чтобы быть переданной вперед, должна быть отправлена ​​на ссылку rvalue (как в идеальной пересылке).

Почему это неправильно/бесполезно?

+8

«Литой ссылка на rvalue reference «не является« идеальной отправкой ». Это * движение *. –

+0

Совершенная переадресация - это комбинация специального правила вывода аргумента шаблона и свертывания ссылок. – Simple

+2

Также: совершенная пересылка включает в себя «универсальные ссылки», и у вас нет универсальной ссылки; у вас есть ссылка rvalue. 'std :: move' здесь достаточно. – Simple

ответ

13

Это не неправильно использовать std::forward здесь (сам по себе), но это неуместно и, таким образом, вводит в заблуждение (в том смысле, можно сказать, что это является на самом деле не так).

Способ, которым вы произносите «приведение чего-то к ссылке rvalue к его типу», является std::move. Это только вещь, которая std::move делает-это static_cast<T&&>, где вам не нужно указывать T.

std::forward - это другой зверь, предназначенный для использования с совершенной пересылкой. Совершенная пересылка происходит только в шаблонах, где возможны ссылки пересылки. Ссылка на пересылку является ссылкой, которая, благодаря специальному правилу на языке, может выводить либо ссылку на lvalue, либо ссылку rvalue. Там вам понадобится std::forward<T>, чтобы повторно установить соответствующую категорию значений (lvalue или rvalue).

Игрушка пример:

void print(int &) 
{ 
    std::cout << "Lvalue\n"; 
} 

void print(int &&) 
{ 
    std::cout << "Rvalue\n"; 
} 

template <class T> 
void perfectForwarder(T &&v) 
{ 
    print(std::forward<T>(v)); 
} 

int main() 
{ 
    int i; 
    perfectForwarder(i); 
    perfectForwarder(std::move(i)); 
    perfectForwarder(42); 
} 

Выходной сигнал будет:

именующее
Rvalue
RValue

[Live]

+3

Я бы сказал, что 'std :: forward' определенно здесь не так, точно так же, как нечитаемый код ошибочен независимо от того, работает он или нет. – bames53

+0

Спасибо! Теперь я понял! – Dean

+3

Я бы не сказал, что это «лишний» *. Это скорее * вводит в заблуждение * (читателю). – Nawaz

Смежные вопросы