c++ - 我如何引用 std::sin(const valarray<double> &)?

标签 c++ function-pointers functional-programming

我在使用一些 valarray 时遇到了问题函数指针代码:

double (*fp)(double) = sin;
valarray<double> (*fp)(const valarray<double> &) = sin;

第一次编译,第二次给出:

error: no matches converting function 'sin' to type 'class std::valarray<double> (*)(const class std::valarray<double>&)'

最佳答案

这会编译,使用 __typeof__海湾合作委员会扩展。看起来像 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)));

关于c++ - 我如何引用 std::sin(const valarray<double> &)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1353757/

相关文章:

安卓 OpenGL : GLbyte LoadShader conversion

c++ - 使用模板 <class InputIterator> string (InputIterator begin, InputIterator end) 时出现奇怪的错误;

c++ - 使用 std::optional 通过引用将 std::vector<int> 传递给函数

c++ - 以特定格式读取文件

c++ - 将函数指针与单例对象一起使用 C++

c++ - 使用枚举成员模板化成员函数

haskell - Haskell 中的新行

filter - 使用 Racket 构建过滤器内置函数

functional-programming - Clojure 中的延续

c++ - 将非静态方法指针作为参数传递给另一个方法