【发布时间】:2014-08-25 01:23:42
【问题描述】:
我有一个高阶函数 map,它类似于 STL for_each,并将 std::function 对象映射到 vector 的事物上。
template<class T, class U>
vector<U> map(function<U (T)> f, vector<T> xs) {
vector<U> ret;
for (auto &x: xs)
ret.push_back(f(x));
return ret;
}
现在,我想让这个高阶函数同时获取 function<int (const vector<T>&)> 和 function<int (vector<T>)> 类型的对象,如所附的最小示例所示。
问题在于function<int (const vector<T>&)> 和function<int (vector<T>)> 似乎可以相互转换(请参阅head 和head2),但map 不会采用const 引用版本function<int (const vector<int>&)>(请参阅@ 987654334@).
可以通过显式转换 (Q2) 告诉 map 接受 const 引用版本,但这相当麻烦。
我想知道,一般来说,是否可以编写一个函数 deref,从 function<int (const vector<T>&)> 中删除 const 引用并返回 function<int (vector<T>)>?
(如果以上是可能的,那么我将不必为 const refs 编写两个相同的 map 重载/实现)。
谢谢。
#include <vector>
#include <functional>
using namespace std;
template<class T, class U>
vector<U> map(function<U (T)> f, vector<T> xs) {
vector<U> ret;
for (auto &x: xs)
ret.push_back(f(x));
return ret;
}
int main() {
vector<vector<int>> m;
function<int (const vector<int>&)> head = [](const vector<int>& a) {return a[0];};
function<int (const vector<int>&)> head1 = [](vector<int> a) {return a[0];}; //conversion OK
function<int (vector<int>)> head2 = [](const vector<int>& a) {return a[0];}; //conversion OK
map(head2,m); //OK
map(head,m); //Q1: problem line, implicit conversion NOT OK
map(function<int (vector<int>)>(head),m); //Q2: explicit conversion OK
map(deref(head),m); //Q3: ??How-to, deref takes a std::function f and returns a function with const ref removed from its signature
return 0;
}
--- 编辑 ---
我对 deref 类似的函数或元函数特别感兴趣,它可以从 std::function 对象的类型签名中删除 const ref,这样我至少可以自动执行 Q2。
我知道,正如@Brian 和@Manu 正确指出的那样,使用std::function 来指定类型不是常规的,但我想知道我上面问的是否可行。 个人,我认为std::function 的代码更清晰,考虑到泛型函数类型Func<T1, T2, T3, ...,Tn, Tresult> 在C# 中是如何使用的。这是如果类型擦除的成本是可以容忍的。
我完全同意 c++ 可以推断返回类型并在类型错误时给出错误消息。也许这只是一个口味问题,我更愿意在编写函数签名时把它拼出来。
【问题讨论】:
-
不要使用
std::function作为map函数参数。只使用一个模板。这减少了您正在试验的耦合,并提高了性能,允许编译器进行内联。
标签: c++ c++11 std-function