2014-10-24 16 views
1

В приведенном ниже коде, почему я должен использовать std::forward при передаче аргументов?Почему я должен использовать std :: forward?

class Test { 
    public: 
    Test() { 
     std::cout << "ctor" << std::endl; 
    } 
    Test(const Test&) { 
     std::cout << "copy ctor" << std::endl; 
    } 
    Test(const Test&&) { 
     std::cout << "move ctor" << std::endl; 
    } 
}; 

template<typename Arg> 
void pass(Arg&& arg) { 
    // use arg.. 
    return; 
} 

template<typename Arg, typename ...Args> 
void pass(Arg&& arg, Args&&... args) 
{ 
    // use arg... 
    return pass(args...); // why should I use std::forward<Arg>(args)... ? 
} 

int main(int argc, char** argv) 
{ 
    pass(std::move<Test>(Test())); 

    return 0; 
} 

код с или без std::forward не показывает копировать/перемещать вокруг.

+1

род занятий; http://stackoverflow.com/questions/3582001/advantages-of-using-forward – Niall

+2

http://stackoverflow.com/questions/7257144/when-to-use-stdforward-to-forward-arguments – Drax

+0

3834459 как насчет над двумя сообщениями вы сбиваетесь с толку? Или они отвечают на вашу проблему? – Yakk

ответ

5

Есть много хороших постов на то, что делает std::forward и как это работает (например, here и here).

В двух словах он сохраняет категорию значений своего аргумента. Идеальная пересылка заключается в том, чтобы аргумент, предоставляемый функции, перенаправляется на другую функцию (или используется внутри функции) с той же категорией значений (в основном, r-value vs. l-value) как originally provided. Он обычно используется с функциями шаблонов, где возможно reference collapsing (с использованием универсальных/пересылающих ссылок).

Рассмотрим пример кода ниже. Снятие std::forward распечатывает requires lvalue и добавляет std::forward отпечатки requires rvalue. func перегружен в зависимости от того, является ли оно значением rvalue или lvalue. Вызов его без std::forward вызывает неправильную перегрузку. В этом случае требуется std::forward, так как pass вызывается с rvalue.

#include <utility> 
#include <iostream> 
class Test { 
    public: 
    Test() { 
     std::cout << "ctor" << std::endl; 
    } 
    Test(const Test&) { 
     std::cout << "copy ctor" << std::endl; 
    } 
    Test(Test&&) { 
     std::cout << "move ctor" << std::endl; 
    } 
}; 

void func(Test const&) 
{ 
    std::cout << "requires lvalue" << std::endl; 
} 

void func(Test&&) 
{ 
    std::cout << "requires rvalue" << std::endl; 
} 

template<typename Arg> 
void pass(Arg&& arg) { 
    // use arg here 
    func(std::forward<Arg>(arg)); 
    return; 
} 

template<typename Arg, typename ...Args> 
void pass(Arg&& arg, Args&&... args) 
{ 
    // use arg here 
    return pass(std::forward<Args>(args)...); 
} 

int main(int, char**) 
{ 
    pass(std::move<Test>(Test())); 
    return 0; 
} 
+0

Почему было бы неправильно вызвать Test const & version? Я имею в виду: какая в этом цена? – Dean

+1

@ user3834459 Зависит от того, что делает функция. Если функциональность между двумя перегрузками требует (или оптимизирована) для категории значений, то да, иначе, вероятно, нет. В общем, учитывая две перегрузки, остается предположить, что есть какая-то разница, и было бы лучше назвать правильную версию. – Niall

+0

Хорошо, понял. Благодаря! – Dean

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