Reputation: 1080
I currently have a series of C++ functions that each call to a C function located elsewhere, these functions essentially do the same thing but return different types. I would like to be able to dynamically get the type of a template and call the associated function, something like
template<typename T>
T getVal(const char* id) {
return funcMap[T.someIdentifyingMethod](id);
}
Is this possible and if so how would I go about it?
Upvotes: 0
Views: 279
Reputation: 41780
I usually use this trick. It associate a type with an object:
using type_id_t = void(*)();
template<typename T> void type_id(){}
Now, we can match an object (in your case, a function) with the function pointer of this template:
std::map<type_id_t, void(*)(const char*)> funcs;
And fill the map:
funcs[type_id<int>] = myFunc1;
funcs[type_id<double>] = myFunc2;
funcs[type_id<SomeOtherType>] = myFunc3;
Now you can retrieve them like this:
template<typename T>
T getVal(const char* id) {
return reinterpret_cast<T(*)(const char*)>(funcMap[type_id<T>])(id);
}
Upvotes: 0
Reputation: 238351
Template specialization indeed sems like what you're looking for. Here's how to specialize your free function, instead of a static member function that Simple proposed:
template<typename T>
T getVal(const char* id); // leave undefined to fail compilation when no specialization exists
template<>
int getVal(const char* id) {
return c_function_that_returns_int(id);
}
template<>
foo getVal(const char* id) {
return c_function_that_returns_foo(id);
}
Upvotes: 1
Reputation: 40080
I'd go this way:
#include <functional>
template<typename ReturnType>
class fget
{
typedef std::function<ReturnType(const char*)> func_type;
func_type _f;
public:
fget() = delete;
fget(const func_type& f) : _f(f) {};
ReturnType operator()(const char* id) { return _f(id); }
};
double minusPi(const char* id) { (void) id; return -3.14; }
unsigned long long getull(const char* id) { (void) id; return 123456789123456; }
#include <iostream>
int main()
{
fget<double> mPi{minusPi};
fget<unsigned long long> ull{getull};
std::cout << mPi("hello") << std::endl;
std::cout << ull("hello") << std::endl;
return 0;
}
Compile & run with:
clang++ -std=c++14 -O2 -Wall -Wextra -pedantic -Werror -pthread main.cpp && ./a.out
Live exemple on Coliru. Output:
-3.14
123456789123456
Upvotes: 0
Reputation: 14390
It sounds like you just want template specialisation:
template<typename T>
struct wrapper;
template<>
struct wrapper<int>
{
static int getVal(char const* id) { /* ... */ }
};
template<>
struct wrapper<widget>
{
static widget getVal(char const* id) { /* ... */ }
};
Then you would call wrapper<T>::getVal(id)
.
Upvotes: 3