Rob*_*arl 6 c++ functional-programming function-pointers
我遇到一些valarray函数指针代码有问题:
double (*fp)(double) = sin;
valarray<double> (*fp)(const valarray<double> &) = sin;
Run Code Online (Sandbox Code Playgroud)
第一次编译,第二次编译:
error: no matches converting function 'sin' to type 'class std::valarray<double> (*)(const class std::valarray<double>&)'
Run Code Online (Sandbox Code Playgroud)
Joh*_*itb 11
这是使用__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;
}
Run Code Online (Sandbox Code Playgroud)
编辑:请参阅AProgrammer的标准报价,了解为什么GCC可以做到这一点.
编辑:符合标准的解决方法
在没有__typeof__严格遵守标准的情况下这样做有点棘手.您需要获得返回类型sin.正如Eric Niebler 所示,您可以使用条件运算符.它的工作原理是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>())));
}
Run Code Online (Sandbox Code Playgroud)
如果你想立即获得地址,你可以写,work这样它就会fp再次返回.
template<typename T>
T addy(T fp, id<T>) { return fp; }
Run Code Online (Sandbox Code Playgroud)
现在,您最终可以编写一个宏来封装条件运算符技巧,并在需要获取任何此类数学函数的地址时使用它.
#define DEDUCE(FN,Y) (1 ? ded_ty() : genFTy<Y>(FN(std::valarray<Y>())))
Run Code Online (Sandbox Code Playgroud)
要获取地址并将其传递给某个通用函数,以下工作原理
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)));
Run Code Online (Sandbox Code Playgroud)
APr*_*mer 10
26 3.1/3
如果valarray的所有const成员函数也适用于此类型,则允许返回valarray的任何函数返回另一种类型的对象.
目的是允许使用模板表达式来优化结果(即每次计算时在整个数组上循环一次,直接分配给生成的valarray <>而不是构建临时).
z = sin(x+y);
Run Code Online (Sandbox Code Playgroud)
可以优化到
for (i = 0; i < N; ++i)
z[i] = sin(x[i] + y[i]);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1042 次 |
| 最近记录: |