Question: My system defines multiple `unordered_map`-like data, e.g.

```
      std::unordered_map< int,  int>  int_map;
      std::unordered_map< int,  double>  double_map;
      std::unordered_map< string,  string>  string_map;
      std::unordered_map< string,  string>  string_map_2;
      ...
      std::unordered_map< string, vector<string> >  string_string_map;
      std::unordered_map< string, vector<string> >  string_string_map_2;

```

Each map holds different data types. These are used with a framework (written in C) that registers callback functions. The registration function (`register_undo_handler`) takes two arguments: a pointer to the callback function and data to be passed to the callback. In our case, the data is a map pointer.

```
    //register our callback function to UNDO framework
    register_undo_handler(clear_data, &int_map);
    //or :
    register_undo_handler(clear_data, &string_map);

    // this is a sketch of the callback function, which frees the map resources
    void clear_data(void *data)
    {  
       data->clear();   
    }

```

If an UNDO happens, the UNDO framework will call each defined callback function, e.g. `clear_data`, and pass the registered data, cast to `void*`, as the parameter like this

```
   // For each registered callback function, run with registered parameter
   (*registered_callback_func)(data); 

```

We want to have a single callback function that can free any map.
Any suggestion on the implementation?

Answer: 
you can have single **template** to do it if you just don't want to dupe code.

```
#include <functional>
#include <unordered_map>
#include <iostream>
using namespace std;

void register_undo_handler(void(*callback)(void*), void* data){
    callback(data); //I'd not gonna implement all undo in C so let me do this instead
}

template<typename clearable>
void Erase(void* data){
    ((clearable*)data)->clear();
}

int main(){
   std::unordered_map<int,  int>  int_map;
   std::unordered_map<int,  double>  double_map;

   double_map[0] = int_map[0] = 0;

   //you can wrap this into a function to avoid type types yourself
   register_undo_handler(&Erase<decltype(int_map)>, (void*)&int_map);
   register_undo_handler(&Erase<decltype(double_map)>, (void*)&double_map);

   std::cout << int_map.size() << ' ' << double_map.size();
}

```
When an "undo" callback is invoked, there are two pieces of information available, namely the address of the function to call and the pointer-sized data to provide to the function. Your requirement is for the first piece to not vary, so it is up to the second piece to tell us what type of map is involved. A big problem is that once a pointer is cast to `void*`, there is no longer a way to recover its original type. So to accomplish the stated goal, you would need a way to identify the map with something other than a raw pointer. One possibility is wrapping the pointer in an object that could remember the original type. This can get messy, especially if you need to dynamically allocate these wrapper objects. The overhead for coding this is more than for writing multiple callback functions. Similarly, there is no savings in runtime overhead (neither time nor space). This is probably not what you want to do.

It is much simpler to write a callback for each type. It takes only a few lines of code to define the callbacks. Each function compiles into a small amount of object code; taken together, the compiled functions are almost the theoretical minimum amount of object code required for any solution. (Each map type's `clear` function is a distinct function, so it takes distinct function calls to potentially call each of them. I'm above the minimum because I check for null.)

```
template <class T>
void call_clear(void * ptr)
{
    if ( ptr )
        static_cast<T*>(ptr)->clear();
}

```

Registering one of these callbacks is a bit of a syntactic pain (e.g. `register_undo_handler( call_clear<decltype(int_map)>, &int_map);`), so it might be desirable to write a wrapper to handle the registration. This wrapper can deduce the template parameter, reducing the amount of repetitive typing. The compiler should inline this function at any level of optimization, resulting in no additional runtime overhead.

```
template <class T>
void register_undo_call_clear(T & map)
{
    register_undo_handler(call_clear<T>, &map);
}

```

At this point, registering the callback is done simply with, for example, `register_undo_call_clear(int_map);`.