假设我有两个已经预先定义的数学函数:
float sqrtf(float a);
double sqrt(double a);
我有一些用C ++编写的模板化代码,我想在两者之间自动切换:
template<typename Precision>
void foo(Precision arg) {
sqrt<Precision>(arg); // Call into sqrtf or sqrt depending on type?
}
是否有一种简便的方法可以完成上述操作而不必手动重写所有重载?
为清楚起见进行编辑:这些是C和CUDA函数(例如BLAS),没有预先建立的重载。
答案 0 :(得分:5)
感谢C ++ 17的if constexpr
,它非常简单
template <typename...>
struct always_false { static constexpr bool value = false; }; // used to make the static_asset value a dependent value otherwise it always fires
template<typename Precision>
void foo(Precision arg) {
if constexpr (std::is_same_v<Precision, double>)
sqrt(arg);
else if constexpr (std::is_same_v<Precision, float>)
sqrtf(arg);
else
static_assert(always_false<Precision>::value, "foo can only be called with the types double or float");
}
如果您不能使用C ++ 17,则可以为foo
和double
专门化或重载float
,并让那些专门化/重载调用正确的函数。
答案 1 :(得分:2)
我想您正在使用C functions。如果您改用C++ functions(C ++具有重载),则不需要玩任何花招:
template<typename Precision>
void foo(Precision arg) {
std::sqrt(arg); // Calls the right overload depending on type of arg
}
因此,痛苦的是我实际上需要支持4种类型:浮动, double,complex_float,complex_double
如果必须使用c函数,则可以编写包装器。编写一个sqrt
,它可以分配给正确的C函数:
template <typename T>
T my_sqrt(T x);
template<>
float my_sqrt(float x) { return sqrtf(x); }
以及其他三种类型的类似专业。然后在foo
中调用该包装器
template<typename Precision>
void foo(Precision arg) {
my_sqrt(arg);
}
答案 2 :(得分:0)
在C ++ 17之前,您可以编写调用相应函数的模板专业化版本:
template<class NumericType>
typename std::enable_if<std::is_same<NumericType, double>::value, void>::type foo(const NumericType number) {
return sqrt(number);
}
以及您需要的类似重载。