1

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;
cigien
  • 50,328
  • 7
  • 37
  • 78
user2725742
  • 312
  • 2
  • 11
  • You could give `Callback` an extra template parameter, say `template struct Callback;`. Then you can stamp out separate instances simply by giving them distinct tags. – Igor Tandetnik Mar 04 '21 at 14:26
  • @IgorTandetnik that sounds great, but I am doing something wrong. The compiler tells me I am supplying 2 template arguments and it should be 1. As suggested I changed ```template struct Callback;``` and then the first line when setting it up ```Callback::func = std::bind(print1, std::placeholders::_1);``` – user2725742 Mar 04 '21 at 18:11
  • Did you also add the tag parameter to the specialization? – Igor Tandetnik Mar 04 '21 at 18:25
  • No, I did not follow through well on that, but updated my question with what I ended up with and is working. If you "answer" the question I will select it as a solution. – user2725742 Mar 05 '21 at 11:55

0 Answers0