I need a template class that maps a family non-overloaded, non-template c-function into C++ template function in order to make subsequent code more generic:
For example suppose, a C-library has these function for a bunch of types:
c_fun_float(...)
c_gun_float(..)
c_fun_double(...)
c_gun_double(..)
That I want to generally call as
cpp<T>::fun(...)
cpp<T>::gun(..)
in C++11.
For that, I am using this pattern:
template<class T> cpp;
template<> cpp<double>{
"static fun maps to c_fun_double"; // pseudo code
"static gun maps to c_gun_double"; // pseudo code
};
template<> cpp<float>{
"static fun maps to c_fun_float"; // pseudo code
"static gun maps to c_gun_float"; // pseudo code
};
The question is how write this mapping code. The first attempt was (maybe abusing of C++11):
template<> cpp<double>{
static constexpr auto fun = &c_fun_double; // nice short code!
static constexpr auto gun = &c_gun_double;
};
... corresponding code for float ...
Which look pretty clean. However I later realized that these are pointers to functions not "real" functions (for example cannot be inlined?). On the other hand they are constexpr
so maybe in effect it the can direct call (unlikely).
So I decided to change the code to
template<> cpp<double>{
template<class... Args>
static inline auto fun(Args&&... args) -> decltype(c_fun_double(std::forward<Args>(args)...)){
return c_fun_double(std::forward<Args>(args)...);
} // lots of typing!
template<class... Args>
static inline auto gun(Args&&... args) -> decltype(c_gun_double(std::forward<Args>(args)...)){
return c_gun_double(std::forward<Args>(args)...);
}
// perhaps write a macro
};
... corresponding code for float ...
The question is, what is better? to have
- a static constexpr function pointer (less verbose, may(?) have indirect call penalty) or
- a static inline perfect forward function (more verbose, but direct call, works with overloads if necessary).
Is there an advantage in one approach over the other?
Maybe another way to put the question, do constexpr
pointers to function produce indirect calls via a runtime pointer?