C++相当于C#的Func<T,TResult>
C++ equivalent of C#'s Func<T, TResult>
以下代码计算items
集合中T
特定属性的平均值:
public double Average<T>(IList<T> items, Func<T, double> selector)
{
double average = 0.0;
for (int i = 0; i < items.Count; i++)
{
average += selector(items[i])
}
return average / items.Count;
}
然后我可以用lambda
表达式来调用它:
double average = Average(items, p => p.PropertyName);
我该如何在c++中进行此操作?到目前为止,我拥有的是:
template <typename T>
double average(const vector<T>& items, ?)
{
double average= 0.0;
for (int i = 0; i < items.size(); i++)
{
average += ?;
}
return average/ items.size();
}
我该如何用c++lambda
来调用它呢?
编辑:非常感谢大家,这是我最终得到的:
template <typename T>
double average(const vector<T>& items, function<double(T)> selector)
{
double result = 0.0;
for (auto i = items.begin(); i != items.end(); i++)
{
result += selector(*i);
}
return result / items.size();
}
并且在main()
:中
zombie z1;
z1.hit_points = 10;
zombie z2;
z2.hit_points = 5;
items.push_back(z1);
items.push_back(z2);
double average = average<zombie>(items, [](const zombie& z) {
return z.hit_points;
});
等效的东西是std::function<double(T)>
。这是一个多态函数对象,可以接受任何具有正确operator()
的函数对象,包括lambda、手写函子、绑定成员函数和函数指针,和强制执行正确的签名。
不要忘记,在C#中,Func
接口(或类,我忘记了)被写为Func<T, Result>
,而C++的std::function
被写为result(T)
。
哦,另外,如果你没有C++0x,TR1和Boost中都有一个,所以你应该可以很容易地访问它。
template <typename T, typename Selector>
double average(const vector<T>& items, Selector selector)
{
double average= 0.0;
for (int i = 0; i < items.size(); i++)
{
average += selector(items[i]);
}
return average / items.size();
}
您可以使用任何可调用和可复制的内容作为选择器。
template <typename T>
double average(const vector<T>& items, double(*selector)(T))
{
double average= 0.0;
for (int i = 0; i < items.size(); i++)
{
average += selector(items[i]);
}
return average/ items.size();
}
请注意,这不是最好的方法,它只是最容易写和理解的方法。正确的方法是使用函子,这样它也可以与C++0x的lambda表达式一起使用。
有很多方法,具体取决于您想要做什么,解决方案的通用性和可重用性如何,您可以接受哪些内存限制(即连续布局的内存与一些链表等)。但这里有一个使用C++03:的简单示例
#include <vector>
#include <list>
#include <iostream>
template <typename Iter, typename Selector>
inline double
average (Iter it, Iter end, Selector selector)
{
double average = 0.0;
size_t size = 0;
while (it != end)
{
average += selector (*it);
++size;
++it;
}
return size != 0 ? average / size : 0.0;
}
struct DoublingSelector
{
template <typename T>
inline T operator () (const T & item)
{
return item * 2;
}
};
int main ()
{
std::vector<int> data;
data.push_back (1);
data.push_back (3);
data.push_back (5);
std::cout << "The average is: " <<
average (data.begin (), data.end (),
DoublingSelector ()) << std::endl;
}
例如,假设您只能接受高级容器(而不是数组)可能会容易得多。您可以通过抛出C++0x来获得lambdas,例如:
#include <vector>
#include <iterator>
#include <iostream>
template <typename C, typename Selector>
inline double
average (const C & items, Selector selector)
{
auto it = std::begin(items);
auto end = std::end(items);
// Average is only meaningful on a non-empty set of items
assert(it != end);
double sum = 0.0;
size_t size = 0;
for (; it != end; ++it)
{
sum += selector(*it);
++size;
}
return sum / size;
}
int main ()
{
std::vector<int> data = { 1, 3, 5 };
std::cout << "The average is: " <<
average (data, [] (int v) { return v * 2; }) << std::endl;
}
选择权在你:-)
附言:是的,std::function
(实际上是C++0x之前Boost的东西)可以用来让你的算法成为非模板。否则,它只会限制您可以传递的"选择器"。
相关文章:
- EASTL矢量<向量<int>>连续的
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- C 字符串比较“祝您好运”&gt;“再见”
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- C 操作员&gt;&gt;与突变器过载
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 是否需要使用 - &gt;运算符在C 中调用成员函数时
- 什么是模板&lt;&gt;inline bla bla
- 编辑C Qlist&lt; object*&gt; gt;QML代码和一些QML警告中的模型
- eigen :: llt&lt;eigen :: matrixxd&gt;具有不完整的类型
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- 错误c++visual studio c2227左侧'->;Init';必须指向类/结构/联合/泛型类型
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy
- ``这个''不能用this-&gt;指针变量
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是std :: set&lt; std :: future&gt;不可能存在
- 使用shared_ptr<字符串>转换为一个无序集合<字符串>
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾
- opencv 2.4.7在iOS错误背景_segm.hpp #include&lt; list&gt;未找到