I have a class that is trying to encapsulate the setup of an interrupt. I need to pass an instantiated reference/pointer/etc to an external function that then calls my function.
I can't change this function:
typedef void (*voidFuncPtr)(void);
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode);
My Library:
class Buttons ...
bool Buttons::begin(int buttonPin)
{
//attachInterrupt(buttonPin, (this->*func)Buttons::released, HIGH);
attachInterrupt(buttonPin, &Buttons::released, LOW);
return 0;
}
void Buttons::released()
{
numButtonPresses++;
pressLength = millis()-pressStartTime;
pressStartTime = 0;
buttonState=LOW;
}
The problem is that I don't know what to put inside the attachInterupt function in the Buttons::begin method. I am sure I am doing something wrong in the way I am approaching this problem, but I am not sure what it is or what I should do about it. I would greatly appreciate any suggestions!
You're using an old c-style function pointer callback. This does not work for member function of an object. If you can't change the callback, you need to make the Buttons::released function static.
The problem you were facing is that you wanted to pass two pieces of data as your callback: the member function, and a class instance to call that member function on.
With the existing interface, which only accepts a function pointer with no arguments, you might create a static Button object and then write a static wrapper function that calls someStaticButton.released(). Then you could pass the address of this wrapper function as your callback. Justin Time’s answer approaches from a different, and clever, direction: wrap the instance and member in a singleton class, and give that a static member callback function. A simpler way to allow more than one singleton class would be to add a numeric ID as template parameter.
You might also be able to make button::released() a static member function, but your implementation appears to refer to member data. This wouldn’t be an option unless there is only one button in the program, represented by a singleton class.
If you can pass the instance pointer as the first argument to your callback function, or any other argument that can do a round-trip conversion to and from an object pointer (such as void* or any integer as wide as intptr_t), you can make the member function static and pass the this pointer as its argument.
If you can overload attachInterrupt to take a std::function object as your callback, you can do what you originally wanted. This type can represent a static function, a member function, or a closure containing a member function and a this pointer.
You unfortunately say you cannot change the callback function, but perhaps you can extend the interface in a backward-compatible way, such as:
#include <array>
#include <iostream>
#include <functional>
#include <stdint.h>
#include <stdlib.h>
#include <utility>
using std::cout;
using std::endl;
using voidFuncPtr = void(*)(void);
using Callback = std::function<void(void)>;
std::array<Callback, 1> interrupts;
void attachInterruptEx( const uint32_t pin,
Callback&& callback,
const uint32_t /* unused */ )
{
interrupts.at(pin) = std::move(callback);
}
void attachInterrupt( const uint32_t pin,
const voidFuncPtr callbackPtr,
const uint32_t mode )
{
/* Passing callbackPtr to a function that expects Callback&& implicitly
* invokes the constructor Callback(voidFuncPtr). This is sugar for
* std::function<void(void)>(void(*)(void)). That is, it initializes a
* temporary Callback object from callbackPtr.
*/
return attachInterruptEx( pin, callbackPtr, mode );
}
class Buttons {
public:
Buttons() = default;
bool begin(int buttonPin);
void released();
unsigned long buttonPresses() { return numButtonPresses; }
private:
// Empty stub function, probably calls a timer.
unsigned long millis() { return 0; };
static constexpr uint32_t LOW = 0;
uint32_t buttonState = LOW;
unsigned long numButtonPresses = 0;
unsigned long pressStartTime = 0;
unsigned long pressLength = 0;
};
/* Per C++17, a constant known at compile time is not odr-used, so this
* definition is deprecated. Still included out of an abundance of caution.
* It cannot have an initializer.
*/
constexpr uint32_t Buttons::LOW;
bool Buttons::begin(int buttonPin)
{
/* The C++17 Standard says little about the return type of std::bind().
* Since the result is a callable object, a std::function can be initialized
* from it. I make the constructor call explicit in case the return type of
* std::bind is a subclass of std::function in some implementation, and
* it resolves the overload in a way we don't expect.
*/
attachInterruptEx( static_cast<uint32_t>(buttonPin),
Callback(std::bind(&Buttons::released, this)),
LOW );
return false;
}
void Buttons::released()
{
numButtonPresses++;
pressLength = millis()-pressStartTime;
pressStartTime = 0;
buttonState=LOW;
}
int main(void)
{
Buttons buttons;
buttons.begin(0);
interrupts[0]();
// Should be 1.
cout << buttons.buttonPresses() << endl;
return EXIT_SUCCESS;
}
[Note that this code will use the following simplified version of your MCVE, primarily to have an easily-usable callback caller when testing & demonstrating the implementation:]
// Pointer type.
typedef void (*voidFuncPtr)(void);
// Dummy callback callers.
void takesVoidFuncPtr(voidFuncPtr vfp) {
std::cout << "Now calling vfp...\n";
vfp();
std::cout << "vfp called.\n";
}
struct DelayedCaller {
voidFuncPtr ptr;
DelayedCaller(voidFuncPtr p) : ptr(p) {}
void callIt() { return ptr(); }
};
// Simple stand-in for Button.
struct HasMemberFunction {
std::string name;
HasMemberFunction(std::string n) : name(std::move(n)) {}
void memfunc() { std::cout << "-->Inside " << name << ".memfunc()<--\n"; }
void funcmem() { static std::string out("Don't call me, I'm lazy. >.<\n"); std::cout << out; }
};
// Calling instance.
HasMemberFunction hmf("instance");
Ideally, you'd be able to bind the function to an instance with a lambda, and pass that to the consuming function as the callback. Unfortunately, though, capturing lambdas can't be converted to non-member function pointers, so this option isn't viable. However...
[Note that I have omitted proper encapsulation both for brevity, and for a demonstration of this approach's caveats at the end of the answer. I would recommend adding it if you actually use this.]
// Helper.
// Can easily be simplified if desired, Caller and MultiCaller only use FuncPtrTraits::ContainingClass.
namespace detail {
template<typename...> struct Pack {};
template<typename T> struct FuncPtrTraits;
template<typename Ret, typename Class, typename... Params>
struct FuncPtrTraits<Ret (Class::*)(Params...)> {
using ReturnType = Ret;
using ContainingClass = Class;
using ParameterList = Pack<Params...>;
};
template<typename T>
using ContainingClass = typename FuncPtrTraits<T>::ContainingClass;
} // detail
// Calling wrapper.
// Only allows one pointer-to-member-function to be wrapped per class.
template<typename MemFunc, typename Class = detail::ContainingClass<MemFunc>>
struct Caller {
static_assert(std::is_member_function_pointer<MemFunc>::value, "Must be built with pointer-to-member-function.");
static Class* c;
static MemFunc mf;
static void prep(Class& cls, MemFunc mem) { c = &cls; mf = mem; }
static void clean() { c = nullptr; mf = nullptr; }
static void call() { return (c->*mf)(); }
// Constructor is provided for convenience of creation, to effectively tie prep() to deduction guide.
// Note that it operates on static members only.
// Convenient, but likely confusing. ...Probably best not to do this. ;3
Caller(Class& cls, MemFunc mem) { prep(cls, mem); }
// Default constructor is required if we provide the above hax ctor.
Caller() = default;
};
template<typename MemFunc, typename Class> Class* Caller<MemFunc, Class>::c = nullptr;
template<typename MemFunc, typename Class> MemFunc Caller<MemFunc, Class>::mf = nullptr;
We can instead provide the desired behaviour by using a wrapper class, which stores the desired function and instance as static member variables, and provides a static member function that matches voidFuncPtr and contains the actual, desired function call. It can be used like so:
std::cout << "\nSimple caller, by type alias:\n";
using MyCaller = Caller<decltype(&HasMemberFunction::memfunc)>;
MyCaller::prep(hmf, &HasMemberFunction::memfunc);
takesVoidFuncPtr(&MyCaller::call);
MyCaller::clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
// Or...
std::cout << "\nSimple caller, via dummy instance:\n";
Caller<decltype(&HasMemberFunction::memfunc)> caller;
caller.prep(hmf, &HasMemberFunction::memfunc);
takesVoidFuncPtr(&caller.call);
caller.clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
That's a bit of a mess, so a hacky constructor is provided to simplify it.
[Note that this may violate the principle of least astonishment, and thus isn't necessarily the best option.]
std::cout << "\nSimple caller, via hax ctor:\n";
Caller clr(hmf, &HasMemberFunction::memfunc);
takesVoidFuncPtr(&clr.call);
clr.clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
Now, this version only allows one function to be wrapped per class. If multiple functions per class are required, we'll need to expand it a little.
[Note that this would be pretty awkward to typedef, as the optimal template parameter order places the first pointer-to-member-function first, to allow Class to be automatically deduced if only one function needs to be wrapped; the "hax ctor" approach was primarily intended for this version of Caller, although a deduction guide could likely also be used to swap Class and MemFunc.]
[Also note that all wrapped member functions must have the same signature.]
// Calling wrapper.
// Slightly more complex version, allows multiple instances of MemFunc to be wrapped.
template<typename MemFunc, typename Class = detail::ContainingClass<MemFunc>, typename... MemFuncs>
struct MultiCaller {
static_assert(std::is_member_function_pointer<MemFunc>::value, "Must be built with pointer-to-member-function.");
static_assert(std::conjunction_v<std::is_same<MemFunc, MemFuncs>...>, "All pointers-to-member-function must be the same type.");
static Class* c;
static std::array<MemFunc, 1 + sizeof...(MemFuncs)> mfs;
static void prep(Class& cls, MemFunc mem, MemFuncs... mems) { c = &cls; mfs = { mem, mems... }; }
static void clean() { c = nullptr; for (auto& m : mfs) { m = nullptr; } }
// Registered functions are wrapped by index, with index specified as a template parameter to match empty parameter list.
template<size_t N = 0, bool B = (N < mfs.size())>
static void call() {
static_assert(B, "Index must be a valid index for mfs.");
return (c->*mfs[N])();
}
// Constructor is provided for convenience of creation, to effectively tie prep() to deduction guide.
// Note that it operates on static members only.
// Convenient, but likely confusing. Primarily used because instantiation & preparation get really repetitive otherwise.
MultiCaller(Class& cls, MemFunc mem, MemFuncs... mems) { prep(cls, mem, mems...); }
// Default constructor is required if we provide the above hax ctor.
MultiCaller() = default;
};
template<typename MemFunc, typename Class, typename... MemFuncs> Class* MultiCaller<MemFunc, Class, MemFuncs...>::c = nullptr;
template<typename MemFunc, typename Class, typename... MemFuncs> std::array<MemFunc, 1 + sizeof...(MemFuncs)> MultiCaller<MemFunc, Class, MemFuncs...>::mfs = {nullptr};
It can be used by type alias as before, or the "hax ctor" can be used to couple it to a deduction guide like so:
std::cout << "\nMulti-registration caller, by type alias:\n";
using MyMultiCaller = MultiCaller<decltype(&HasMemberFunction::memfunc), HasMemberFunction, decltype(&HasMemberFunction::funcmem)>;
MyMultiCaller::prep(hmf, &HasMemberFunction::memfunc, &HasMemberFunction::funcmem);
takesVoidFuncPtr(&MyMultiCaller::call<0>); // memfunc
takesVoidFuncPtr(&MyMultiCaller::call<1>); // funcmem
MyMultiCaller::clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
// Or...
std::cout << "\nMulti-registration caller, via hax ctor:\n";
MultiCaller mclr(hmf, &HasMemberFunction::memfunc, &HasMemberFunction::funcmem);
takesVoidFuncPtr(&mclr.call<0>); // memfunc
takesVoidFuncPtr(&mclr.call<1>); // funcmem
mclr.clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
Note that in all cases, this has all the caveats of static members. In particular, since the binding relies on the static class members and isn't contained within the wrapper function itself, modifying the members after a callback is passed will immediately change the results of calling said already-passed callback.
std::cout << "\nBut alas:\n";
MyCaller::prep(hmf, &HasMemberFunction::memfunc);
DelayedCaller dc(&MyCaller::call);
dc.callIt(); // Output: "-->Inside instance.memfunc()<--"
std::cout << "Changing the registered instance will...\n";
HasMemberFunction hmf2("spinstance");
MyCaller::c = &hmf2;
dc.callIt(); // Output: "-->Inside spinstance.memfunc()<--"
You can see the different variants here, on Compiler Explorer.
Compiling my code that contains this class:
class Dessin
{
private:
vector<Figures*>T;
public:
void ajouteFigure(const Figures& f) const
{
for(auto element: T)
{
T.push_back(f);
}
}
};
yields an error:
[Error] no matching function for call to
'std::vector::push_back(const Figures&) const'
This is what I'm supposed to do in the main()
Dessin s;
s.ajouteFigure(Cercle(1.1));
Why wouldn't this work?
Assuming Cercle is a class name, you're trying to push a value where a pointer is expected.
To "fix" the error you should change your ajouteFigure prototype to accept Figures pointers and non-const this:
void ajouteFigure(Figures* f)
Then you should call it passing a pointer to a Figures object, i.e. created with a new expression:
s.ajouteFigure(new Cercle(1.1));
That being said, this code seems pointless. You're adding the pointer as many times as you have elements in the vector (which is always 0 in the example you provided).
Using raw pointers is also unadvised, you should use smart pointers like std::unique_ptr, although that would break the current code.
Consider this, less improper, example:
class Dessin
{
private:
vector<unique_ptr<Figures>> T;
public:
void ajouteFigure(unique_ptr<Figures> f)
{
T.push_back(move(f)); // just once
}
};
and at the call site:
Dessin s;
s.ajouteFigure(make_unique<Cercle>(1.1)); // C++≥14
or, if you can't use C++14:
Dessin s;
s.ajouteFigure(unique_ptr<Figures>(new Cercle{1.1}));
Just to add to this, I think you would be better to make it a template function and create the right object inside the function with arguments to the constructor passed as function parameters.
This way you don't have to create a std::unique_ptr or use new every time you call the function.
Here's a basic implementation:
class Dessin{
public:
template<typename T, typename ... Args>
void ajouteFigure(Args &&... args){
figures.emplace_back(new T(std::forward<Args>(args)...));
}
private:
std::vector<std::unique_ptr<Figures>> figures;
};
Then using the class is less error-prone:
int main(){
Dessin d;
d.ajouteFigure<Cercle>(1.1);
}
I have a number of function pointers bound with their respective class objects:
ExampleClass EO;
std::function<void()> Example=std::bind(&ExampleClass::ExampleFunction, &EO);
However, I'd like to 'unbind' these at a later point, specifically to identify the specific class which each of the 'std::function's relate to.
auto Unbind(std::function<void()> &Example)->void
{
//Find which object &Example is bound with (in this case EO/ExampleClass)
}
What's the best way of doing this?
std::function performs type erasure. As per the name, it erases the real underlying types from the interface.
There is no way back from there.
If you want to preserve the type of the target object, then std::mem_fn might be what you want:
http://en.cppreference.com/w/cpp/utility/functional/mem_fn
You cannot do it with a function object.
A possibility is to construct a wrapper in which to store the reference to the method and the object.
Something like this:
template<typename T, typename Fn>
struct MemberFunctionPointer {
MemberFunctionPointer(T* ref, Fn fn) : m_ref(ref),
m_method(fn) { }
template<typename... Args>
auto operator()(Args&&... args) {
return (m_ref->*m_method)(std::forward<Args...>(args)...);
}
T* m_ref = nullptr; // a reference (pointer) to the object instance
Fn m_method = nullptr; // a reference to the function method
};
Note: this is just a scratch. You should add a more sophisticated interface. Moreover a helper function in order to create a MemberFunctionPointer object could be useful as well.
You can pass that kind of object instead of a simply function.
struct Foo {
void bar() {
// something
}
};
int main(int argc, char *argv[]) {
Foo f;
MemberFunctionPointer<Foo, decltype(&Foo::bar)> method(&f, &Foo::bar);
method(); // call the method on the object f.
assert(&f == method.get_obj_reference());
return 0;
}
AbstractFieldCollection is the base class of hardwareMissingAlarm, etc.
hardwareMissingAlarm belongs to another class that is a template.
alarmFieldCollection.push_back((AbstractAlarmField Device::*) &Device::hardwareMissingAlarm);
alarmFieldCollection.push_back((AbstractAlarmField Device::*) &Device::hardwareErrorAlarm);
alarmFieldCollection.push_back((AbstractAlarmField Device::*) &Device::badConfigAlarm);``
Then in another function I'm reading the vector like this:
for(int32_t i=0; i<alarmFieldCollection.size(); i++)
{
AbstractAlarmField Device::* pAF = alarmFieldCollection[i];
std::cout << "isRaised: "<< pDev << std::endl;
if ((pDev->*pAF).isRaised(pContext))
{
.....
}
}
and pDev is the Device object, however pDev->*pAF returns NULL. In fact when I'm printing &Device::hardwareErrorAlarm, &Device::hardwareMissingAlarm the result is 1. I don't know what I'm doing wrong.
isRaised is a method that belongs to the class AbstractAlarmField.
Thanks in advance.
You provided almost no code but it seems like you are storing an abstract object by value, not by reference or pointer. This may lead to object slicing and any kind of memory problem as a consequence. Try to use AbstractAlarmField& as the type of Device fields instead.
It is not useful to convert a member pointer X C::* to Y C::*. The Standard allows it as a reinterpret_cast or C-style cast, but with entirely unspecified results (unless you convert back to the original type). You would be better off using a virtual functor to safely get the AbstractAlarmField subobject:
#include <type_traits>
#include <memory>
struct AlarmGetter {
public:
virtual ~AlarmGetter();
virtual AbstractAlarmField& get(Device& dev) const = 0;
};
template <typename T>
struct AlarmMemberPtr
: public AlarmGetter {
static_assert(std::is_base_of<AbstractAlarmField, T>::value,
"Member type is not an AbstractAlarmField");
public:
explicit AlarmMemberPtr(T Device::*member)
: m_member( member ) {}
virtual AbstractAlarmField& get(Device& dev) const {
return dev.*m_member;
}
private:
T Device::*m_member;
};
template <typename T>
std::unique_ptr<AlarmGetter> make_alarm_getter(T Device::*member) {
std::unique_ptr<AlarmGetter> ptr(new AlarmMemberPtr<T>(member));
return ptr;
}
// To populate:
std::vector<std::unique_ptr<AlarmGetter>> alarmFieldCollection;
alarmFieldCollection.push_back(make_alarm_getter(&Device::hardwareMissingAlarm));
alarmFieldCollection.push_back(make_alarm_getter(&Device::hardwareErrorAlarm));
alarmFieldCollection.push_back(make_alarm_getter(&Device::badConfigAlarm));
// To use:
if (alarmFieldCollection[i]->get(*pDev).isRaised(pContext))
If it might be useful, you could also easily add an overload
virtual const AbstractAlarmField& get(const Device& dev) const;
Has anyone ever used pointers/references/pointer-to-member (non-type) template parameters?
I'm not aware of any (sane/real-world) scenario in which that C++ feature should be used as a best-practice.
Demonstation of the feature (for pointers):
template <int* Pointer> struct SomeStruct {};
int someGlobal = 5;
SomeStruct<&someGlobal> someStruct; // legal c++ code, what's the use?
Any enlightenment will be much appreciated!
Pointer-to-function:
Pointer-to-member-function and pointer-to-function non-type parameters are really useful for some delegates. It allows you to make really fast delegates.
Ex:
#include <iostream>
struct CallIntDelegate
{
virtual void operator()(int i) const = 0;
};
template<typename O, void (O::*func)(int)>
struct IntCaller : public CallIntDelegate
{
IntCaller(O* obj) : object(obj) {}
void operator()(int i) const
{
// This line can easily optimized by the compiler
// in object->func(i) (= normal function call, not pointer-to-member call)
// Pointer-to-member calls are slower than regular function calls
(object->*func)(i);
}
private:
O* object;
};
void set(const CallIntDelegate& setValue)
{
setValue(42);
}
class test
{
public:
void printAnswer(int i)
{
std::cout << "The answer is " << 2 * i << "\n";
}
};
int main()
{
test obj;
set(IntCaller<test,&test::printAnswer>(&obj));
}
Live example here.
Pointer-to-data:
You can use such non-type parameters to extend the visibility of a variable.
For example, if you were coding a reflexion library (which might very useful for scripting), using a macro to let the user declare his classes for the library, you might want to store all data in a complex structure (which may change over time), and want some handle to use it.
Example:
#include <iostream>
#include <memory>
struct complex_struct
{
void (*doSmth)();
};
struct complex_struct_handle
{
// functions
virtual void doSmth() = 0;
};
template<complex_struct* S>
struct csh_imp : public complex_struct_handle
{
// implement function using S
void doSmth()
{
// Optimization: simple pointer-to-member call,
// instead of:
// retrieve pointer-to-member, then call it.
// And I think it can even be more optimized by the compiler.
S->doSmth();
}
};
class test
{
public:
/* This function is generated by some macros
The static variable is not made at class scope
because the initialization of static class variables
have to be done at namespace scope.
IE:
class blah
{
SOME_MACRO(params)
};
instead of:
class blah
{
SOME_MACRO1(params)
};
SOME_MACRO2(blah,other_params);
The pointer-to-data template parameter allows the variable
to be used outside of the function.
*/
std::auto_ptr<complex_struct_handle> getHandle() const
{
static complex_struct myStruct = { &test::print };
return std::auto_ptr<complex_struct_handle>(new csh_imp<&myStruct>());
}
static void print()
{
std::cout << "print 42!\n";
}
};
int main()
{
test obj;
obj.getHandle()->doSmth();
}
Sorry for the auto_ptr, shared_ptr is available neither on Codepad nor Ideone.
Live example.
The case for a pointer to member is substantially different from pointers to data or references.
Pointer to members as template parameters can be useful if you want to specify a member function to call (or a data member to access) but you don't want to put the objects in a specific hierarchy (otherwise a virtual method is normally enough).
For example:
#include <stdio.h>
struct Button
{
virtual ~Button() {}
virtual void click() = 0;
};
template<class Receiver, void (Receiver::*action)()>
struct GuiButton : Button
{
Receiver *receiver;
GuiButton(Receiver *receiver) : receiver(receiver) { }
void click() { (receiver->*action)(); }
};
// Note that Foo knows nothing about the gui library
struct Foo
{
void Action1() { puts("Action 1\n"); }
};
int main()
{
Foo foo;
Button *btn = new GuiButton<Foo, &Foo::Action1>(&foo);
btn->click();
return 0;
}
Pointers or references to global objects can be useful if you don't want to pay an extra runtime price for the access because the template instantiation will access the specified object using a constant (load-time resolved) address and not an indirect access like it would happen using a regular pointer or reference.
The price to pay is however a new template instantiation for each object and indeed it's hard to think to a real world case in which this could be useful.
The Performance TR has a few example where non-type templates are used to abstract how the hardware is accessed (the hardware stuff starts at page 90; uses of pointers as template arguments are, e.g., on page 113). For example, memory mapped I/O registered would use a fixed pointer to the hardware area. Although I haven't ever used it myself (I only showed Jan Kristofferson how to do it) I'm pretty sure that it is used for development of some embedded devices.
It is common to use pointer template arguments to leverage SFINAE. This is especially useful if you have two similar overloads which you couldn't use std::enable_if default arguments for, as they would cause a redefinition error.
This code would cause a redefinition error:
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
void foo (T x)
{
cout << "integral";
}
template <typename T, typename = std::enable_if_t<std::is_floating_point<T>::value>>
void foo (T x)
{
cout << "floating";
}
But this code, which utilises the fact that valid std::enable_if_t constructs collapse to void by default, is fine:
// This will become void* = nullptr
template <typename T, std::enable_if_t<std::is_integral<T>::value>* = nullptr>
void foo (T x)
{
cout << "integral";
}
template <typename T, std::enable_if_t<std::is_floating_point<T>::value>* = nullptr>
void foo (T x)
{
cout << "floating";
}
Occasionally you need to supply a callback function having a particular signature as a function pointer (e.g. void (*)(int)), but the function you want to supply takes different (though compatible) parameters (e.g. double my_callback(double x)), so you can't pass its address directly. In addition, you might want to do some work before and after calling the function.
It's easy enough to write a class template that tucks away the function pointer and then calls it from inside its operator()() or some other member function, but this doesn't provide a way to extract a regular function pointer, since the entity being called still requires the this pointer to find the callback function.
You can solve this problem in an elegant and typesafe way by building an adaptor that, given an input function, produces a customised static member function (which, like a regular function and unlike a non-static member function, can have its address taken and used for a function pointer). A function-pointer template parameter is needed to embed knowledge of the callback function into the static member function. The technique is demonstrated here.