用相同的代码循环遍历对象和指针
C++ Looping through objects and pointers with the same code
我有两个容器
set<Person>
vector<Person*>
是否有任何方法对以下转换lambda代码进行修改,以便任何一个容器都可以使用?
transform(container.begin(), container.end(), back_inserter(data),
[](const Person* p) { return PairResults(p->getTime(), p->getName()); }
);
现在我只能让它作用在向量上
谢谢。
>>解决方案代码在这里
非常感谢Andrew在这方面的帮助!
您可以使用函数重载的一个小技巧来做到这一点:定义两个生成指向Person
指针的函数,如下所示:
const Person* make_ptr(const Person* p) { return p; }
const Person* make_ptr(const Person& p) { return &p; }
下一个问题是统一lambda元素的类型:不幸的是,说[](auto p) {...}
并让编译器为您选择Person
或Person*
是不合法的。使用模板解决了这个问题:
template<typename T, typename R>
void xform(vector<T>& from, vector<R>& to) {
transform(from.begin(), from.end(), back_inserter(to),
[&](T &p) { return PairResults(make_ptr(p)->getTime(), make_ptr(p)->getName()); }
);
}
现在一切工作-你可以调用xform
与Person
或Person*
的容器,并得到正确的结果。
您可以使用代理对象接受指向Person或ref指向Person的指针,并为它们提供指针语义:
实例:http://ideone.com/Wk2VMx
#include <algorithm>
#include <iostream>
#include <vector>
#include <set>
#include <string>
struct Person {
int age;
std::string name;
};
class PersonProxy {
public:
PersonProxy(Person& p)
: person(&p) {}
PersonProxy(Person* p)
: person(p) {}
Person& operator*() { return *person; }
Person* operator->() { return person; }
private:
Person* person;
};
int main()
{
std::vector<Person> p1;
p1.push_back(Person{42, "Bob"});
Person bill{30, "Bill"};
std::set<Person*> p2;
p2.insert(&bill);
std::vector<int> data;
auto the_lambda = [](PersonProxy pp) {return pp->age;};
std::transform(p1.begin(), p1.end(), std::back_inserter(data), the_lambda);
std::transform(p2.begin(), p2.end(), std::back_inserter(data), the_lambda);
for (int age : data)
{
std::cout << age << "n";
}
}
另一种方法是使用函子而不是lambda,并定义operator()(Person&)
和operator()(Person*)
,但上面的方法是提供一种可以编写lambda的类型,并且可以使用从Person
和Person*
进行隐式转换。
可能会像下面这样工作
template <class T> struct MakePair {
PairResults operator () (const T & p) {
return PairResults(p.getTime(), p.getName());
}
};
template <class T> struct MakePair<T*> {
PairResults operator () (const T * p) {
return PairResults(p->getTime(), p->getName());
}
};
typedef decltype (* (container.begin ())) container_element_type;
transform(container.begin(), container.end(), back_inserter(data),
[] (const container_element_type & p) {
return MakePair<container_element_type> {} (p);
}
);
在我看来,很难实现你所需要的,这表明你的代码中缺少一些抽象。
例如,谁负责处置vector中的堆分配对象?考虑将容器的实现细节隐藏在具有良好定义接口的PersonContainer
后面。
相关文章:
- 如何正确地推回然后遍历堆中对象的向量?
- 尝试重载输出运算符时,我无法遍历对象向量
- C++类对象 - 遍历基于参数的对象
- 遍历对象向量,并找到与从文本文件中提取的对象匹配的变量
- Rapidjson 遍历并获取复杂 JSON 对象成员的值
- 如何使用 PHPCPP 传递对象数组,遍历每个对象并返回关联数组
- 如何遍历 QStack 对象的元素
- C++遍历对象并获取其地址
- 在循环遍历矢量时将对象添加到矢量
- 创建并遍历一个模板化对象数组
- 以旧方式C++遍历对象指针数组(没有基于范围的 for)
- JSONcpp遍历对象中的列表
- C++:遍历对象以调用相同的方法
- 类型为 <对象*>和遍历的矢量
- 循环遍历对象的地址
- 用相同的代码循环遍历对象和指针
- 设计数据结构来存储多键对象集,以便能够收集和遍历该集的超平面
- 在对象外部循环遍历unique_ptr集合
- C++:遍历对象的所有成员?
- 在连续内存中遍历具有公共基类的对象