【发布时间】:2018-05-02 00:32:15
【问题描述】:
我希望能够编写这样的代码:
SplineFunction<Polynomial<3>> cubicSplineFunction;
// ... here be some additional code to populate the above object ...
auto dydx = cubicSplineFunction.transform<Polynomial<2>>(const Polynomial<3>& cubicSpline){
return cubicSpline.derivative();
};
auto dsdx = cubicSplineFunction.transform<T/*?*/>([](const Polynomial<3>& cubicSpline){
Polynomial<2> dy = cubicSpline.derivative();
Polynomial<4> dsSquared = dy*dy + 1*1;
return [dsSquared](double x){ // Fixed in response to comment: capture by value
return std::sqrt(dsSquared);
};
});
dydx(1.0); // efficient evaluation of cubicSplineFunction's derivative
dsdx(2.0); // efficient evaluation of cubicSplineFunction's arc rate
所以我实现了下面的类。但是我应该用什么类型代替上面的 T(第 8 行)来表示“可以通过签名 double(double) 调用的东西”?
template<typename S>
struct SplineFunction {
std::vector<S> splines;
auto operator()(double t) const {
int i = static_cast<int>(t);
return splines[i](t - i);
}
template<typename R, typename F>
SplineFunction <R> transform(F f) const {
SplineFunction <R> tfs;
for (const auto& s : splines) {
tfs.splines.push_back(f(s));
}
return tfs;
}
// ... MORE CODE ...
}
template<int N>
struct Polynomial {
std::array<double, N+1> coeffs;
double operator()(double x) const;
Polynomial<N - 1> derivative() const;
// ... MORE CODE ...
}
template<int L, int M>
Polynomial<L+M> operator*(const Polynomial<L>& lhs, const Polynomial<M>& rhs);
template<int L>
Polynomial<L> operator+(Polynomial<L> lhs, double rhs);
// ... MORE CODE ...
【问题讨论】:
-
危险,威尔罗宾逊!第二个
transform调用创建一个通过引用捕获局部变量的lambda,然后将该lambda 返回给调用者。调用者得到的是一个持有悬空引用的 lambda。 -
"something callable with signature
double(double)"可以拼写为std::function<double(double)> -
另一种可能性是完全删除
R参数并推断返回类型:template<typename F> auto transform(F f) const -> SplineFunction<decltype(f(std::declval<S>()))> { ... } -
@IgorTandetnik 您可以使用
std::function拼写它,但只能使用开销(在性能和大小方面)。在这种情况下可能无关紧要,但值得指出。
标签: c++ c++11 templates lambda