#cpp #cpp11
Наткнулся тут на вопрос про std::bind и возник вопрос. Чем отличается способ с шаблоном templatevoid display( int a[], size_t n, Operation op ) // или Operation&& { for ( size_t i = 0; i < n; i++ ) { std::cout << op( a[i] ) << ' '; } std::cout << std::endl; } от void display( int a[], size_t n, std::function operation ) { //... } и от void display( int a[], size_t n, int operation( int ) ) { } Какие возможности и ограничения у того или иного способа, когда их нужно применять.
Ответы
Ответ 1
Первый вариант принимает любой объект, не проверяя его тип. Так, если туда передать что-то, что не может быть вызвано, или что-то, что возвращает тип, который не может быть использован в cout, то получите не совсем релевантную ошибку компиляции. Второй вариант принимает любой объект, который может быть вызван. При это согласованность сигнатур проверяется сразу и выдаётся релевантная ошибка, что позволяет быстрее понять, где проблема. Третий вариант принимает лишь свободные функции и лямбды без состояний и является более ограниченным чем второй вариант. Использовать третий вариант в современном C++ коде нет никакого смысла. Касательно применения: стоит всегда использовать std::function, за исключением тех моментов, когда это по каким-то причинам вредит.Ответ 2
Первый способ передает функтор в метод статически - что позволяет компилятору заинлайнить его вызов, если функтор достаточно короткий. Второй способ позволяет избавиться от шаблонов - но ценой вызова виртуального метода; такой метод уже не получится заинлайнить в общем случае (тем не менее, компилятор все еще может заинлайнить его если перед этим заинлайнил display). Третий способ позволяет передать только функцию, но не функтор.Ответ 3
Если переданная функция вызывается в цикле, то предпочтительнее передавать ее как шаблонный параметр, чтобы компилятор мог ее заинлайнить. Обычно функторы - это небольшие объекты, и их можно передавать по значению. Если возможности для инлайна нет (например переданная функция кладется в list>), то можно сразу использовать параметр с типом function . Указатель на функцию следует использовать только если всегда будет передаваться и храниться именно указатель на функцию. std::function<> имеет размер около 4 указателей (зависит от реализации), и иногда хочется избежать x4 расходов на хранение и копирование, если известно что надо хранить только указатели на функции.
Комментариев нет:
Отправить комментарий