Почему или когда я должен приводить параметры вызываемой функции к rvalue перед вызовом? - PullRequest
0 голосов
/ 06 июля 2018

До сих пор я рассматривал прохождение и вызов вызываемого как

template <class Fct, class... Args> void f(Fct&& g, Args&&... args)
{
    g(std::forward<Args>(args)...);
}

это путь. Теперь в этом разговоре (при 34 мин.) И в реализации примера std :: invoke я увидел эквивалент приведенного выше фрагмента, который условно преобразует вызываемый объект в ссылку на rvalue перед вызывая его,

template <class Fct, class... Args> void f(Fct&& g, Args&&... args)
{
    std::forward<Fct>(g)(std::forward<Args>(args)...);
}

Я предполагаю, что эта модификация влияет только на замыкания, но я все еще не понимаю, почему вторая версия предпочтительнее: приведение влияет только на аргументы rvalue, и никакое состояние не должно копироваться при вызове, верно? Я также проверил, перегружены ли std :: function :: operator () на & и &&, чтобы получить подсказку библиотеки, альтернативную приведенным выше фрагментам, но это не так.

Заранее спасибо за подсказки и ответы!

1 Ответ

0 голосов
/ 06 июля 2018

Смысл идеальной пересылки - максимально сохранить исходную информацию.

g(std::forward<Args>(args)...); удалит информацию rvalue / lvalue исходного функционального объекта, g будет всегда обрабатываться как lvalue.

Это вызовет наблюдаемый эффект, например:

struct foo {
    void operator()(int) & {
        std::cout << "& called\n";
    }

    void operator()(int) && {
        std::cout << "&& called\n";
    }
};

foo{}(1) вызовет второе operator(). Если вы используете свой первый подход без std::forward, f(foo{}, 1) вызовет первый operator().

...