I have found that using the code in the linked answer/below works well, but has problems in my use case. It effectively creates a "static wrapper" to a non-static member function, to be passed as a callback.
#include <stdio.h>
#include <functional>
template <typename T>
struct Callback;
template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
template <typename... Args>
static Ret callback(Args... args) {
return func(args...);
}
static std::function<Ret(Params...)> func;
};
template <typename Ret, typename... Params>
std::function<Ret(Params...)> Callback<Ret(Params...)>::func;
So I have that bit in a header file and then various classes have code like below. The problem is that when trying to define two such callbacks within the same scope the second overrides the first.
typedef int (*callback_t)(int*,int*);
Callback<int(int*,int*)>::func = std::bind(&myClass::myMethod1, this, std::placeholders::_1, std::placeholders::_2);
callback_t func1 = static_cast<callback_t>(Callback<int(int*,int*)>::callback);
register_task1_with_library(func1);
Callback<int(int*,int*)>::func = std::bind(&myClass::myMethod2, this, std::placeholders::_1, std::placeholders::_2);
callback_t func2 = static_cast<callback_t>(Callback<int(int*,int*)>::callback);
register_task2_with_library(func2);
The callback registered first is redirected to the second. What is the minimal change to create a second "static wrapper" for something like this? It seems the entire contents of the header file have to be duplicated, replacing Callback with something like Callback2, to have a second "static wrapper" available.
And an easier example to work with that shows the same problem:
#include <iostream>
#include "callback.hpp"
void print1(std::string msg)
{
std::cout << "print1:\t" << msg << std::endl;
}
void print2(std::string msg)
{
std::cout << "print2:\t\t" << msg << std::endl;
}
int main(int argc, char ** argv)
{
typedef void (*callback_t)(std::string);
Callback<void(std::string)>::func = std::bind(print1, std::placeholders::_1);
callback_t func1 = static_cast<callback_t>(Callback<void(std::string)>::callback);
Callback<void(std::string)>::func = std::bind(print2, std::placeholders::_1);
callback_t func2 = static_cast<callback_t>(Callback<void(std::string)>::callback);
func1("howdy");
func2("partner");
return 0;
}
Related items: https://stackoverflow.com/a/29817048/2725742 and Using a c++ class member function as a c callback function, thread safe version
The modified templates are below are what I ended up with after a comment discussion and my testing suggests it is fine in my use cases. The added 'tag' parameter helps keep each item unique.
template <typename T, int tag = 0>
struct Callback;
template <typename Ret, typename... Params, int tag>
struct Callback<Ret(Params...), tag> {
template <typename... Args>
static Ret callback(Args... args) {
return func(args...);
}
int m_tag = tag;
static std::function<Ret(Params...)> func;
};
template <typename Ret, typename... Params, int tag>
std::function<Ret(Params...)> Callback<Ret(Params...), tag>::func;