При использовании шаблонов для поддержки функтора в качестве аргументов, какой классификатор мне следует использовать? - PullRequest
0 голосов
/ 01 июля 2018

Рассмотрим этот код:

template<class F>
void foo1(F f) { f(); }

template<class F>
void foo2(F const& f) { f(); }

template<class F>
void foo3(F&& f) { f(); }

Какую версию foo мне следует использовать? foo1 - это то, что я вижу больше всего «в дикой природе», но я боюсь, что это может привести к появлению копий, которые мне не нужны. У меня есть специальный функтор, который довольно тяжело копировать, поэтому я бы хотел этого избежать. В настоящее время я склоняюсь к foo3 (так как foo2 не допустит мутирующих функторов), но я не уверен в последствиях.

Я нацеливаюсь на C ++ 11.

1 Ответ

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

Я бы предпочел foo3 вместо foo1 (хотя тело должно быть std::forward<F>(f)();)

foo3 приведет к тому, что тип F будет выведен к типу, который позволяет вам полностью пересылать аргумент из-за свертывания ссылки . Это полезно, так как вы не будете делать копии чего-либо по умолчанию и можете поддерживать категорию значений (lvalue vs rvalue), если решите, что хотите перенаправить функтор к чему-то, что действительно требует его копирования.

В общем, первая форма (foo1) подходит, если ваша функция будет хранить свою собственную копию функтора, но третья форма (foo3) лучше подходит для пересылки (использования) аргументов.

Я также рекомендую отличный пост Скотта Мейерса о универсальных ссылках , а также этот связанный вопрос переполнения стека .

...