Best way of passing callback function parameters in C++

夙愿已清 提交于 2019-12-30 03:57:04

问题


What is the best way of passing a callback function parameter in C++?

I thought of simply using templates, like this:

template <typename Function>
void DoSomething(Function callback)

This is the way used e.g. in std::sort for the comparison function object.

What about passing using &&? E.g.:

template <typename Function>
void DoSomething(Function&& callback)

What are the pros and cons of those two methods, and why does the STL uses the former e.g. in std::sort?


回答1:


The

template <typename Function>
void DoSomething(Function&& callback)

… which uses a forwarding reference to pass by reference, is IMHO superior for the case where the function just uses the callback. Because a functor object, although usually small, can be arbitrarily large. Passing it by value then incurs some needless overhead.

The formal argument can end up as T&, T const& or T&& depending on the actual argument.


On the other hand, passing a simple function pointer by reference involves an extra needless indirection, which in principle could mean some slight overhead.

If in doubt whether this is significant for a given compiler, system and application, then measure.


Regarding

why does the STL uses the former [passing by value] e.g. in std::sort?

… it's worth noting that std::sort has been there since C++98, well before forwarding references were introduced in C++11, so it could not have that signature originally.

Possibly there just has not been sufficient incentive to improve this. After all, one should generally not fix that which works. Still, extra oveloads with an “execution policy” argument are introduced in C++17.

Since this concerns a possible C++11 change, it's not covered by the usual source for rationales, namely Bjarne Stroustrup's “The design and evolution of C++”., and I do not know of any conclusive answer.


Using the template<class F> void call( F ) style, you can still get back "pass by reference". Simply do call( std::ref( your callback ) ). std::ref overrides operator() and forwards it to the contained object.

Simularly, with template<class F> void call( F&& ) style, you can write:

template<class T>
std::decay_t<T> copy( T&& t ) { return std::forward<T>(t); }

which explicitly copies something, and force call to use a local copy of f by:

call( copy(f) );

so the two styles mainly differ in how they behave by default.





回答2:


Since this is C++11 (or higher): <functional> and std::function are your best friends here.

#include <iostream>
#include <functional>
#include <string>


void DoSomething(std::function<void()> callback) {
    callback();
}

void PrintSomething() {
   std::cout << "Hello!" << std::endl;
}

int main()
{
    DoSomething(PrintSomething);
    DoSomething([]() { std::cout << "Hello again!" << std::endl; });
}


来源:https://stackoverflow.com/questions/40588734/best-way-of-passing-callback-function-parameters-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!