C++使用相同的代码循环遍历对象和指针

Dav*_*vid 5 c++ pointers stl

所以我有两个容器

set<Person>
vector<Person*>
Run Code Online (Sandbox Code Playgroud)

是否有任何方法可以修改以下转换lambda代码,以便可以使用任何容器?

transform(container.begin(), container.end(), back_inserter(data),
          [](const Person* p) { return PairResults(p->getTime(), p->getName()); }
);
Run Code Online (Sandbox Code Playgroud)

现在我只能让它在矢量上工作.

谢谢.

>> 解决方案代码

非常感谢安德鲁对这个问题的帮助!

das*_*ght 5

您可以使用函数重载的小技巧来完成它:定义两个产生指针的函数Person,如下所示:

const Person* make_ptr(const Person* p) { return p; }
const Person* make_ptr(const Person& p) { return &p; }
Run Code Online (Sandbox Code Playgroud)

下一个问题是统一lambda元素的类型:遗憾的是,说[](auto p) {...}并让编译器选择PersonPerson*为你选择是不合法的.使用模板解决了这个问题:

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()); }
    );
}
Run Code Online (Sandbox Code Playgroud)

现在一切正常-你可以调用xform用的容器PersonPerson*,并得到正确的结果.

在ideone上演示.


And*_*rew 4

您可以使用一个代理对象,它接受指向 Person 的指针或对 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";
    }

}
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用仿函数而不是 lambda,并定义operator()(Person&)operator()(Person*),但上述方法是提供一个类型,您可以使用该类型编写 lambda,并且可以使用该类型进行隐式Person转换Person*