使用__typeof__ GCC 扩展进行编译。看起来 GCC 的 valarray 使用表达式模板来延迟计算窦。但这会使sin 模板的返回类型不完全是valarray<T>,而是一些奇怪的复杂类型。
#include <valarray>
template<typename T> struct id { typedef T type; };
int main() {
using std::valarray;
using std::sin;
id<__typeof__(sin(valarray<double>()))>::type (*fp)(const valarray<double> &) = sin;
}
编辑:请参阅 AProgrammer 的标准报价,了解为什么 GCC 可以这样做。
编辑:符合标准的解决方法
在没有__typeof__ 的情况下以严格符合标准的方式执行此操作有点棘手。您将需要获取sin 的返回类型。您可以为此使用条件运算符,例如 Eric Niebler has shown。它的工作原理是让sin 函数实际上没有被调用,而只是类型检查。通过尝试将条件运算符的另一个分支(实际计算的分支)转换为相同的类型,我们可以生成一个虚拟参数,以便能够推断出函数指针的类型:
#include <valarray>
using std::valarray;
template<typename T> struct id {
typedef T type;
};
struct ded_ty {
template<typename T>
operator id<T>() { return id<T>(); }
};
template<typename E, typename T>
id<T(*)(valarray<E> const&)> genFTy(T t) {
return id<T(*)(valarray<E> const&)>();
}
template<typename T>
void work(T fp, id<T>) {
// T is the function pointer type, fp points
// to the math function.
}
int main() {
work(std::sin, 1 ? ded_ty() : genFTy<double>(std::sin(valarray<double>())));
}
如果你想马上得到地址,你可以写work让它再次返回fp。
template<typename T>
T addy(T fp, id<T>) { return fp; }
现在,您终于可以编写一个宏来封装条件运算符的诡计,并在您想要获取任何此类数学函数的地址时使用它。
#define DEDUCE(FN,Y) (1 ? ded_ty() : genFTy<Y>(FN(std::valarray<Y>())))
要获取地址并将其传递给某个通用函数,则可以使用以下方法
std::transform(v1.begin(), v1.end(), v1.begin(),
addy(std::sin, DEDUCE(std::sin, double)));
std::transform(v2.begin(), v2.end(), v2.begin(),
addy(std::cos, DEDUCE(std::cos, double)));