【发布时间】:2014-08-05 07:44:58
【问题描述】:
我正在研究一些速记函数式编程方法来帮助用 C++ 进行数据分析,我遇到了一种情况,我觉得我的实现应该可以工作,但 g++ 不同意我的看法。见以下代码:
#include <algorithm>
#include <valarray>
#include <functional>
#include <iostream>
using namespace std;
//generates a list of [from,to] in increments of step. last is <= to with precision of step
template<typename T> std::valarray<T> range(T from, T to, T step = 1) {
size_t elems = (size_t)floor((to-from)/step) + 1;
std::valarray<T> result(elems);
for (int i = 0; i < elems; i++) {
result[i] = from+step*i;
}
return result;
}
//map over multiple lists as arguments to the provided function
template<typename T, typename... Ts> void mapthreadv(std::function<void(T,Ts...)> func, std::valarray<T> &in, std::valarray<Ts>&... rest) {
for (int i = 0; i < in.size(); i++) {
func(in[i],rest[i]...);
}
}
int main(int argc, char **argv) {
auto first = range(0.0,1.0,0.1);
auto second = range(0.0,10.0,1.0);
auto third = range(0.0,100.0,10.0);
mapthreadv<double,double,double>([](double a, double b, double c) { cout << '{' << a << ',' << b << ',' << c << "},"; },first,second,third);
}
预期输出为:
{0,0,0},{0.1,1,10},{0.2,2,20},{0.3,3,30},{0.4,4,40},{0.5,5,50},{0.6,6,60},{0.7,7,70},{0.8,8,80},{0.9,9,90},{1,10,100},
这可以通过直接指定<void(double,double,double)> 而不是<void(T,Ts...)> 到std::function 来实现,但这显然不是一个有用的修复。代码编译失败,错误与模板参数扣除/替换有关:
‘main(int, char**)::<lambda(double, double, double)>’ is not derived from ‘std::function<void(double, Ts ...)>’
所以我的直觉是,出于某种原因,Ts 没有被扩展......我有任何指示或明显的疏忽吗?一般来说,我对模板函数很陌生,因此感谢您提供任何帮助。
【问题讨论】:
-
这很有趣,我得到的错误是
error: 'cout' was not declared in this scope。 -
这里不需要使用
std::function,直接将仿函数的类型作为模板参数即可:template<typename F, typename T, typename... Ts> void mapthreadv(F func, /*...*/)。 -
另外,
range为range(0.0, 1.0, 0.3)返回了太多元素,因为 0.3 不能均匀地划分为 1.0。不幸的是,我想不出一个适用于双精度和整数的简单修复方法。连double都在自找麻烦。 -
我忘记在我的原始帖子中包含
using namespace std;