Context
(C++11) As part of a safeguard in a piece of serialization code, I want to check if a function pointer is known. (Otherwise, the deserialization mechanism will probably fail).
This is a (simplified) piece of code that illustrates the mechanism:
template <typename Fun>
struct FunctionCallRegistry
{
static std::unordered_map<Fun, std::string>& FunctionMap()
{
static std::unordered_map<Fun, std::string> map;
return map;
}
static void Register(Fun function, std::string name)
{
auto& map = FunctionMap();
auto it = map.find(function);
if (it == map.end())
{
map.insert(std::pair<Fun, std::string>(function, name));
// other code follows...
}
}
static void Ensure(Fun function)
{
auto& map = FunctionMap();
auto it = map.find(function);
if (it == map.end())
{
throw std::exception("Function not found.");
}
}
};
// Registration code:
struct FunctionCallRegistryInitializer
{
template <typename Ret, typename... Args>
explicit FunctionCallRegistryInitializer(Ret(*function)(Args...),
const char* name)
{
FunctionCallRegistry<Ret(*)(Args...)>::Register(function, name);
}
};
#define RegisterFunction(fcn) FunctionCallRegistryInitializer fcn_reg_##__COUNTER__(&fcn, #fcn);
Serialization is now easy, given that we can lookup a function and emit the name. Similarly, deserialization looks up the name and emits the function factory wrapped in a class (this is the easy part).
Registration works as follows: basically for each function, I'll call Register with a function pointer and a name (which is used for the (de)serialization). There's a macro involved here and a few helper classes to do the plumbing. E.g.:
struct Testje
{
static int test(int lhs, int rhs) {
std::cout << lhs << " + " << rhs << std::endl;
return lhs + rhs;
}
};
RegisterFunction(Testje::test);
The type of Fun here is f.ex. void (*fcn)(int, int). This works fine, because test is a static function and hence not a member function. Remove the 'static' and the horror begins...
Problem
When I attempt to compile this code in MSVC++, I get an error that tells me function-to-member pointers cannot be hashed:
error C2338: The C++ Standard doesn't provide a hash for this type.
In an attempt to solve this, I've tried to cast fcn to another pointer type, which doesn't seem to be allowed as well.
Note that member function pointers aren't required to be unique; I just need a unique ID for each member function pointer with the same signature since Fun is a template. It's also easy to ensure that the name is unique by simply throwing an exception if it's registered twice.
Question
This leaves me with the simple question: what will work? How can I check if a function pointer is registered?