我正在尝试在 C++ 中实现除差公式,因为它看起来 here .
到目前为止我已经做到了
template<typename F, typename T>
T divdiff(F f, T t1, T t2) {
return (f(t1) - f(t2)) / (t1 - t2);
};
template<typename F, typename T, typename... Args>
T divdiff(F f, T tstart, Args... t, T tend) {
return (divdiff(f, tstart, t...) - divdiff(f, t..., tend))/ (tstart - tend);
};
它编译得很好,但是当它尝试像这样使用它时
double r = divdiff([](double x) { return 2 * x; }, 1.0, 2.0, 3.0);
我收到以下错误
note: candidate function not viable: requires 3 arguments, but 4 were provided
T divdiff(F f, T tstart, Args... t, T tend) {``
我的编译器是 gcc
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 8.0.0 (clang-800.0.42.1) Target: x86_64-apple-darwin15.4.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin
有谁知道为什么它不起作用以及如何修复它
最佳答案
template<typename F, typename T, typename... Args> T divdiff(F f, T tstart, Args... t, T tend)
自 Args... t
不在参数列表末尾,则不会被推导。不允许进行此类推导,部分原因是为了简化语言规则,部分原因是为了帮助保持程序简单(并防止搬起石头砸自己的脚)。您可以指定 Args ...
明确喜欢 divdiff<F, double, double>
,但是对于递归调用,很难删除最后一个 double
.
无论如何,可变参数模板方法都会遭受模板膨胀和效率低下的问题,因为参数列表可能会被每个函数调用复制。由于序列的元素应该都是相同的类型,因此请考虑使用迭代器。然后您可以使用 std::initializer_list
添加便利的重载用于基于数组的可迭代序列。
template< typename F, typename bidirectional_iterator >
typename std::iterator_traits< bidirectional_iterator >::value_type
divdiff( F f, bidirectional_iterator first, bidirectional_iterator last ) {
bidirectional_iterator next = std::next( first );
bidirectional_iterator prev = std::prev( last );
auto diff = next == prev?
f( * first ) - f( * prev )
: divdiff( f, first, prev ) - divdiff( f, next, last );
return diff / ( * first - * prev );
}
template< typename F, typename T >
T divdiff( F f, std::initializer_list< T > il )
{ return divdiff( f, il.begin(), il.end() ); }
Demo .
关于c++ - 使用可变参数模板在 C++ 中实现差异化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41711200/