2014-12-10 2 views
0

Рассмотрим этот код:C++ 11 идеально экспедиторская и ссылка рушится

template<typename T> 
void foo(T&& param){ //In this case && is called universal reference 
    std:string tmp = std::forward<string>(param); 
} 

Мой вопрос, если универсальный ссылочный тип может быть выведен почему мне еще нужно позвонить вперед?
Почему без пересылки правильный c'tor tmp не будет вызываться, даже если был выведен тип T.

Мой второй вопрос о референтных рушится правил:

  1. A& && становится A&
  2. A&& && становится A&&

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

template<class T> 
T&& forward(T&& arg){ 
    return static_cast<T&&>(arg); 
} 

Согласно правилам выше, если тип T имеет значение rvalue, он будет сбрасываться до ссылки rvalue, если тип T - это значение lvalue, оно будет сбрасываться до ссылки lvalue.
Итак, почему у std::forward есть две разные подписи, одна для ссылки lvalue и одна для ссылки rvalue. Я что-то упускаю?

+3

В наши дни они называются «пересылкой ссылок». –

+0

Что такое T $$? это должно быть T &&? – UpAndAdam

ответ

2

Мой вопрос в том, можно ли вывести универсальный ссылочный тип, почему мне еще нужно перезвонить?

Потому что, как только вы даете имя параметра param это именующее, даже если функция была вызвана с RValue, поэтому он не будет направлен в качестве RValue, если вы не используете forward<T>

Почему без пересылки правильный c'tor tmp не будет вызываться, даже если был выведен тип T.

Потому что param является lvalue. Чтобы восстановить категорию значения аргумента, переданного в foo, вам нужно вернуть его обратно в string& или string&&, что означает, что вам нужно знать, что тип T был выведен как, и использовать forward, чтобы сделать актерский состав.

Почему у std::forward есть две разные подписи: одна для ссылки lvalue и одна для ссылки rvalue. Я что-то упускаю?

Он был изменен http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3143.html

Существует много вводной информацию в http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3143.html и http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2951.html

Проблемы с предлагаемой версией является то, что если вы говорите, forward<string> то параметр T не выводится так Безразлично 't используется как ссылка для пересылки, что означает, что T&& не может связываться с lvalue, и он должен иметь возможность привязываться к lvalue для того, чтобы forward<string>(param) работал, потому что param - это lvalue.

+0

В соответствии с вашим ответом параметр foo - это lvalue, когда вы вызываете вперед с lvalue, вы получаете lvalue. Итак, как сохраняется тип rvalue? BTW в соответствии с сигнатурой Скотта Мейерса foo подразумевает, что param является универсальной ссылкой. –

+0

rvalue-ness теряется внутри тела 'foo', потому что' param' - это lvalue, но затем вы возвращаете тип rvalue с помощью 'forward'. –

+0

И теперь они называются [пересылка ссылок] (http://isocpp.org/files/papers/N4164.pdf), а не универсальные ссылки. –

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