In c++, when and how do you use a callback function?
EDIT:
I would like to see a simple example to write a callback function.
In c++, when and how do you use a callback function?
EDIT:
I would like to see a simple example to write a callback function.
There is also the C way of doing callbacks: function pointers
Now if you want to pass in class methods as callbacks, the declarations to those function pointers have more complex declarations, example:
The accepted answer is very useful and quite comprehensive. However, the OP states
So here you go, from C++11 you have
std::function
so there is no need for function pointers and similar stuff:This example is by the way somehow real, because you wish to call function
print_hashes
with different implementations of hash functions, for this purpose I provided a simple one. It receives a string, returns an int (a hash value of the provided string), and all that you need to remember from the syntax part isstd::function<int (const std::string&)>
which describes such function as an input argument of the function that will invoke it.There isn't an explicit concept of a callback function in C++. Callback mechanisms are often implemented via function pointers, functor objects, or callback objects. The programmers have to explicitly design and implement callback functionality.
Edit based on feedback:
In spite of the negative feedback this answer has received, it is not wrong. I'll try to do a better job of explaining where I'm coming from.
C and C++ have everything you need to implement callback functions. The most common and trivial way to implement a callback function is to pass a function pointer as a function argument.
However, callback functions and function pointers are not synonymous. A function pointer is a language mechanism, while a callback function is a semantic concept. Function pointers are not the only way to implement a callback function - you can also use functors and even garden variety virtual functions. What makes a function call a callback is not the mechanism used to identify and call the function, but the context and semantics of the call. Saying something is a callback function implies a greater than normal separation between the calling function and the specific function being called, a looser conceptual coupling between the caller and the callee, with the caller having explicit control over what gets called. It is that fuzzy notion of looser conceptual coupling and caller-driven function selection that makes something a callback function, not the use of a function pointer.
For example, the .NET documentation for IFormatProvider says that "GetFormat is a callback method", even though it is just a run-of-the-mill interface method. I don't think anyone would argue that all virtual method calls are callback functions. What makes GetFormat a callback method is not the mechanics of how it is passed or invoked, but the semantics of the caller picking which object's GetFormat method will be called.
Some languages include features with explicit callback semantics, typically related to events and event handling. For example, C# has the event type with syntax and semantics explicitly designed around the concept of callbacks. Visual Basic has its Handles clause, which explicitly declares a method to be a callback function while abstracting away the concept of delegates or function pointers. In these cases, the semantic concept of a callback is integrated into the language itself.
C and C++, on the other hand, does not embed the semantic concept of callback functions nearly as explicitly. The mechanisms are there, the integrated semantics are not. You can implement callback functions just fine, but to get something more sophisticated which includes explicit callback semantics you have to build it on top of what C++ provides, such as what Qt did with their Signals and Slots.
In a nutshell, C++ has what you need to implement callbacks, often quite easily and trivially using function pointers. What it does not have is keywords and features whose semantics are specific to callbacks, such as raise, emit, Handles, event +=, etc. If you're coming from a language with those types of elements, the native callback support in C++ will feel neutered.
Boost's singals2 allows you to subscribe generic member functions (without templates!) and in a threadsafe way.
Note: Most of the answers cover function pointers which is one possibility to achieve "callback" logic in C++, but as of today not the most favourable one I think.
What are callbacks(?) and why to use them(!)
A callback is a callable (see further down) accepted by a class or function, used to customize the current logic depending on that callback.
One reason to use callbacks is to write generic code which is independant from the logic in the called function and can be reused with different callbacks.
Many functions of the standard algorithms library
<algorithm>
use callbacks. For example thefor_each
algorithm applies an unary callback to every item in a range of iterators:which can be used to first increment and then print a vector by passing appropriate callables for example:
which prints
Another application of callbacks is the notification of callers of certain events which enables a certain amount of static / compile time flexibility.
Personally, I use a local optimization library that uses two different callbacks:
Thus, the library designer is not in charge of deciding what happens with the information that is given to the programmer via the notification callback and he needn't worry about how to actually determine function values because they're provided by the logic callback. Getting those things right is a task due to the library user and keeps the library slim and more generic.
Furthermore, callbacks can enable dynamic runtime behaviour.
Imagine some kind of game engine class which has a function that is fired, each time the users presses a button on his keyboard and a set of functions that control your game behaviour. With callbacks you can (re)decide at runtime which action will be taken.
Here the function
key_pressed
uses the callbacks stored inactions
to obtain the desired behaviour when a certain key is pressed. If the player chooses to change the button for jumping, the engine can calland thus change the behaviour of a call to
key_pressed
(which the callsplayer_jump
) once this button is pressed the next time ingame.What are callables in C++(11)?
See C++ concepts: Callable on cppreference for a more formal description.
Callback functionality can be realized in several ways in C++(11) since several different things turn out to be callable*:
std::function
objectsoperator()
)* Note: Pointer to data members are callable as well but no function is called at all.
Several important ways to write callbacks in detail
Note: As of C++17, a call like
f(...)
can be written asstd::invoke(f, ...)
which also handles the pointer to member case.1. Function pointers
A function pointer is the 'simplest' (in terms of generality; in terms of readability arguably the worst) type a callback can have.
Let's have a simple function
foo
:1.1 Writing a function pointer / type notation
A function pointer type has the notation
where a named function pointer type will look like
The
using
declaration gives us the option to make things a little bit more readable, since thetypedef
forf_int_t
can also be written as:Where (at least for me) it is clearer that
f_int_t
is the new type alias and recognition of the function pointer type is also easierAnd a declaration of a function using a callback of function pointer type will be:
1.2 Callback call notation
The call notation follows the simple function call syntax:
1.3 Callback use notation and compatible types
A callback function taking a function pointer can be called using function pointers.
Using a function that takes a function pointer callback is rather simple:
1.4 Example
A function ca be written that doesn't rely on how the callback works:
where possible callbacks could be
used like
2. Pointer to member function
A pointer to member function (of some class
C
) is a special type of (and even more complex) function pointer which requires an object of typeC
to operate on.2.1 Writing pointer to member function / type notation
A pointer to member function type for some class
T
has the notationwhere a named pointer to member function will -in analogy to the function pointer- look like this:
Example: Declaring a function taking a pointer to member function callback as one of its arguments:
2.2 Callback call notation
The pointer to member function of
C
can be invoked, with respect to an object of typeC
by using member access operations on the dereferenced pointer. Note: Parenthesis required!Note: If a pointer to
C
is available the syntax is equivalent (where the pointer toC
must be dereferenced as well):2.3 Callback use notation and compatible types
A callback function taking a member function pointer of class
T
can be called using a member function pointer of classT
.Using a function that takes a pointer to member function callback is -in analogy to function pointers- quite simple as well:
3.
std::function
objects (header<functional>
)The
std::function
class is a polymorphic function wrapper to store, copy or invoke callables.3.1 Writing a
std::function
object / type notationThe type of a
std::function
object storing a callable looks like:3.2 Callback call notation
The class
std::function
hasoperator()
defined which can be used to invoke its target.3.3 Callback use notation and compatible types
The
std::function
callback is more generic than function pointers or pointer to member function since different types can be passed and implicitly converted into astd::function
object.3.3.1 Function pointers and pointers to member functions
A function pointer
or a pointer to member function
can be used.
3.3.2 Lambda expressions
An unnamed closure from a lambda expression can be stored in a
std::function
object:3.3.3
std::bind
expressionsThe result of a
std::bind
expression can be passed. For example by binding parameters to a function pointer call:Where also objects can be bound as the object for the invocation of pointer to member functions:
3.3.4 Function objects
Objects of classes having a proper
operator()
overload can be stored inside astd::function
object, as well.3.4 Example
Changing the function pointer example to use
std::function
gives a whole lot more utility to that function because (see 3.3) we have more possibilities to use it:
4. Templated callback type
Using templates, the code calling the callback can be even more general than using
std::function
objects.Note that templates are a compile-time feature and are a design tool for compile-time polymorphism. If runtime dynamic behaviour is to be achieved through callbacks, templates will help but they won't induce runtime dynamics.
4.1 Writing (type notations) and calling templated callbacks
Generalizing i.e. the
std_ftransform_every_int
code from above even further can be achieved by using templates:with an even more general (as well as easiest) syntax for a callback type being a plain, to-be-deduced templated argument:
Note: The included output prints the type name deduced for templated type
F
. The implementation oftype_name
is given at the end of this post.The most general implementation for the unary transformation of a range is part of the standard library, namely
std::transform
, which is also templated with respect to the iterated types.4.2 Examples using templated callbacks and compatible types
The compatible types for the templated
std::function
callback methodstdf_transform_every_int_templ
are identical to the above mentioned types (see 3.4).Using the templated version however, the signature of the used callback may change a little:
Note:
std_ftransform_every_int
(non templated version; see above) does work withfoo
but not usingmuh
.The plain templated parameter of
transform_every_int_templ
can be every possible callable type.The above code prints:
type_name
implementation used aboveScott Meyers gives a nice example:
I think the example says it all.
std::function<>
is the "modern" way of writing C++ callbacks.