I'm looking to do something like this:
void func(void *data, const int dtype)
{
typedef typename std::conditional<dtype==0,float,double>::type DataType;
funcT((DataType *)data);
return;
}
This will not compile because dtype needs to be known at compile time. I'm trying to avoid using a switch statement, because I have 8 data types I am working with, with many functions such as the one above, being called from Python via ctypes.
Is there a way something like std::conditional can done during run time, making use of the dtype identifier passed in?
All types must be resolved at compile time. So no type, can ever depend on a runtime parameter to a function. The way to handle something like this is basically to build a visiting mechanism, once, and then you can reuse it. Basically, something like this:
template <class F>
void visit_data(void* data, const int dtype, F f) {
switch (dtype)
case 0: f(*static_cast<float*>(data));
case 1: f(*static_cast<double*>(data));
}
Now you can implement functions by writing visitors:
struct func_impl {
void operator()(float&) { ... }
void operator()(double&) { ... }
};
Your visitor can also use generic code:
struct func_impl2 {
template <class T>
void operator()(T&) { ... }
};
Then you can write your function by leveraging the visitor:
void func(void* data, const int dtype) {
visit_data(data, dtype, func_impl{});
}
The switch case over your list of types will only appear once in your entire codebase. If you add a new type, any visitor that doesn't handle it will give a compile time error if used.
You can also use lambdas to do it inline with a helper function or two; especially useful in 14 where you have generic lambdas.
If you can use C++17 it can be solved with a std::visitor and std::variant like so:
using var_t = std::variant<float, double>;
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
void func(var_t arg) {
std::visit(overloaded {
[](float arg) { foo_float(arg); },
[](double arg) { foo_double(arg); },
}, arg);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With