gpt4 book ai didi

c++ - 在 std::function 模板中扩展参数包

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:43:25 26 4
gpt4 key购买 nike

我正在研究一些速记函数式编程方法来帮助用 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 没有被扩展……我有任何指示或明显的疏忽吗?一般来说,我对模板函数还很陌生,所以非常感谢您的帮助。

最佳答案

问题是当您使用模板参数包时,仍然执行模板参数推导,即使您显式指定类型 (§ 14.8.1 [temp.arg.explicit]/p9):

Template argument deduction can extend the sequence of template arguments corresponding to a template parameter pack, even when the sequence contains explicitly specified template arguments. [ Example:

template<class ... Types> void f(Types ... values);
void g() {
f<int*, float*>(0, 0, 0);
}
// Types is deduced to the sequence int*, float*, int

end example ]

而且,由于 lambda 闭包类型不是 std::function,模板参数推导将失败。

无论如何,没有理由在这里使用std::function;您可以简单地将仿函数作为模板参数:

template<typename F, typename T, typename... Ts> void mapthreadv(F func, std::valarray<T> &in, std::valarray<Ts>&... rest) {
for (int i = 0; i < in.size(); i++) {
func(in[i],rest[i]...);
}
}

这也避免了显式指定模板参数的需要:

mapthreadv([](double a, double b, double c) { std::cout << '{' << a << ',' << b << ',' << c << "},"; },first,second,third);

Demo .

关于c++ - 在 std::function 模板中扩展参数包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25128450/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com