«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Почему std::forward использует шаблон идентификатора для отключения вывода аргументов шаблона?

Почему std::forward использует шаблон идентификатора для отключения вывода аргументов шаблона?

Опубликовано 9 ноября 2024 г.
Просматривать:346

Why does std::forward use the identity template to disable template argument deduction?

Отключение вычета аргументов шаблона с помощью std::forward для обеспечения корректной пересылки

Рассмотрим определение std::forward в VS2010:

template inline
_Ty&& forward(typename identity<_Ty>::type& _Arg)
{   // forward _Arg, given explicitly specified type parameter
    return ((_Ty&&)_Arg);
}

Целью шаблона идентификации является отключение вывода аргументов шаблона. Почему это так важно в данном сценарии?

Вывод аргументов шаблона приведет к неправильному выводу типов. Если ссылка rvalue на объект типа X передается функции шаблона с типом параметра T&, при выводе аргумента шаблона T будет выводиться как X, в результате чего будет получен тип параметра X&. Однако для идеальной пересылки параметр является lvalue, поскольку у него есть имя. Таким образом, использование вывода аргументов шаблона в std::forward приведет к тому, что выведенный тип параметра будет ссылкой на lvalue или константной ссылкой на lvalue.

template
T&& forward_with_deduction(T&& obj)
{
    return static_cast

Рассмотрим следующий пример:

void test(int&){}
void test(const int&){}
void test(int&&){}

template
void perfect_forwarder(T&& obj)
{
    test(forward_with_deduction(obj));
}

int main()
{
    int x;
    const int& y(x);
    int&& z = std::move(x);

    test(forward_with_deduction(7));    //  7 is an int&&, correctly calls test(int&&)
    test(forward_with_deduction(z));    //  z is treated as an int&, calls test(int&)

    //  All the below call test(int&) or test(const int&) because in perfect_forwarder 'obj' is treated as
    //  an int& or const int& (because it is named) so T in forward_with_deduction is deduced as int& 
    //  or const int&. The T&& in static_cast<T&&>(obj) then collapses to int& or const int& - which is not what 
    //  we want in the bottom two cases.
    perfect_forwarder(x);           
    perfect_forwarder(y);           
    perfect_forwarder(std::move(x));
    perfect_forwarder(std::move(y));
}

В этом примере идеальная пересылка не удалась, поскольку параметр в Perfect_forwarder рассматривается как ссылка lvalue или const lvalue из-за его имени. Это приводит к неправильному выводу типа в front_with_deduction, что приводит к нежелательной семантике static_cast.

Отключение вывода аргументов шаблона с помощью шаблона идентификатора в std::forward гарантирует, что std::forward всегда возвращает ссылку rvalue, что важно для правильная идеальная пересылка значений lvalue и rvalue.

Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3