things want achieve similar in post: select function name based on template parameter
in c library, handle different numeric types (float, double, complex -float, complex-double), there functions different names.
when creating wrapper of such c library, figure out way achieve effect of overloading , use same function name numeric types. use template specialization:
#include <iostream> float saxpy(float x) { return (1-x); } double daxpy(double x) { return (1+x); } template <typename t> t axpy(t x); template<> inline float axpy<float>(float x) { return saxpy(x); } template<> inline double axpy<double>(double x) { return daxpy(x); } int main() { auto z0 = axpy(1.0f); auto z1 = axpy(1.0); std::cout << z0 << " " << z1 << std::endl; return 0; } there's way using type traits:
#include <type_traits> #include <iostream> float saxpy(float x) { return (1-x); } double daxpy(double x) { return (1+x); } struct saxpy_traits { static float feval(float x) { return saxpy(x); } }; struct daxpy_traits { static double feval(double x) { return daxpy(x); } }; template <typename t> struct axpy_traits { typedef typename std::conditional<std::is_same<t, float>::value, saxpy_traits, daxpy_traits>::type func; inline static t feval(t x) { return func::feval(x); } }; template<typename t> inline t axpy(t x) { return axpy_traits<t>::feval(x); } int main() { auto z0 = axpy(1.0f); auto z1 = axpy(1.0); std::cout << z0 << " " << z1 << std::endl; return 0; } is there more elegant ways? thank you.
since don't know qualifies "elegant", propose 2 alternative approaches:
float saxpy(float x) { return 1.0f - x; } double daxpy(double x) { return 1.0 + x; } namespace v1 { float axpy(float x) { return saxpy(x); } double axpy(double x) { return daxpy(x); } } // namespace v1 namespace v2 { struct axpy { float operator()(float x) const { return saxpy(x); } double operator()(double x) const { return daxpy(x); } }; static constexpr axpy axpy; } // namespace v2 the first version defines 2 overloaded functions. similar approach taken standard library, e.g. std::sqrt.
the second version defines function object has overloaded operator(). version allows code auch as
std::vector<float> fs { 1.f, 2.f, 3.f, 4.f }; std::vector<float> rs(fs.size()); std::transform(fs.begin(), fs.end(), rs.begin(), v2::axpy); which not compile first version.
Comments
Post a Comment