Как std :: forward определяет тип `_Ty`? - PullRequest
3 голосов
/ 30 мая 2019

Я изучаю шаблоны и особенно std::forward;когда я проверяю его реализацию, он использует другой шаблон класса std::remove_reference в своем списке аргументов:

template<class _Ty>
_Ty&& forward(typename remove_reference<_Ty>::type& _Arg)
{// forward an lvalue as either an lvalue or an rvalue
   // ...
}

Кстати: я удалил несколько вещей, таких как inline, constexpr, NO_EXCEPT и тело функции для ясности

Я читал о том, как типы выводятся, когда параметром шаблона является указатель (_Ty*), ссылка (_Ty &), универсальная ссылка (_Ty) и где это просто сам тип (_Ty).В данном случае это ссылка, но перед ней добавлено removed_reference<_Ty>::type;_Ty и ссылка делятся по вызову на remove_reference.Как компилятор определяет тип _Ty?

Шаблон функции должен выяснить параметры шаблона, используя аргументы, переданные функции (если они не определены явно в вызове функции), но вв этом случае remove_reference также является шаблоном класса, который также должен определить тип _Ty.Для меня это почти как уловка 22, потому что std::forward должен вычислить _Ty, используя аргумент функции, но аргумент функции, равный std::remove_reference<_Ty>, должен уже знать, что такое _Ty.Все это говорит мне о том, что я плохо понимаю, как работают шаблоны, но я не знаю, где.

Ответы [ 3 ]

4 голосов
/ 30 мая 2019

как компилятор определяет тип _Ty?

Это не так. std::forward предназначен для использования с явно указанным типом. И это обеспечивается принятием аргумента функции в std::forward с типом typename remove_reference<_Ty>::type, где _Ty находится в не выводимом контексте . Компилятор не может вывести его.

Типичное использование со ссылкой для пересылки следующее:

template<typename T>
void foo(T&& t) {
    std::forward<T>(t);
}

Строго говоря, std::forward - это просто синтаксический сахар для броска до T&& выше. Это ссылка сворачивается делает всю магию, но голое приведение к T&& не передает намерение продвинуться так же ясно, как названный оператор. Вот почему существует std::forward.

3 голосов
/ 30 мая 2019

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

std::forward<T>(t);

Это противоречит std::move, которое выводит, и обычно используется так:

std::move(t);
2 голосов
/ 30 мая 2019

Как std::forward выводит тип _Ty?

Ty не имеет тип. Ty - это тип (параметр шаблона). Компилятор не не выводит тип.

как компилятор определяет тип _Ty?

Аргумент шаблона должен быть передан явно.

Если тип был выведен, то:

template<class T>
void foo(T&& t) {
    bar(std::forward(t));
}

передаст lvalue, поскольку t является lvalue. Но мы хотим передать rvalue, потому что t является ссылкой на rvalue. Поскольку вычет является контрпродуктивным, он отключается с помощью трюка remove_reference<_Ty>::type&, и мы должны правильно написать:

template<class T>
void foo(T&& t) {
    bar(std::forward<T>(t));
                 // ^^^ this is how the compiler knows
}
...