객체의 벡터가 주어지면 우아한 방법으로 그 멤버를 추출 할 수 있습니까? 나는 현재 for 루프를 사용하고 있지만 그렇게 할 수있는 방법이 있다면 좋을 것이다. 예 :객체의 벡터에서 요소를 추출하십시오.
class Object {
int x;
float y;
}
vector<Object> obj;
// Fill up obj
vector<int> all_x = obj.x // Won't work obviously
객체의 벡터가 주어지면 우아한 방법으로 그 멤버를 추출 할 수 있습니까? 나는 현재 for 루프를 사용하고 있지만 그렇게 할 수있는 방법이 있다면 좋을 것이다. 예 :객체의 벡터에서 요소를 추출하십시오.
class Object {
int x;
float y;
}
vector<Object> obj;
// Fill up obj
vector<int> all_x = obj.x // Won't work obviously
공변 집계를 지원하지 않습니다 (일반 또는 C++) std::vector
, 당신이 원하는 일을 할 구문 꽤 방법이 없습니다. 당신이 괜찮 경우
class getx_iter : public vector<Object>::iterator
{
public:
getx_iter(const vector<Object>::iterator &iter) : vector<Object>::iterator(iter) {}
int operator*() { return (*this)->x; }
};
을 : 당신이 정말로 obj
요소의 x
회원들과all_x
은, 당신은 그렇게 새로운 반복자 클래스를 정의 할 수 있습니다 초기화 하려면
빈 vector
을 초기화 한 다음 labmda로 std::transform
을 채우면 더 명확한 옵션이됩니다 (@andars가 제안한대로).
또한 vector::reserve()
및 back_inserter
를 사용하여 별도의 초기화를 피할 수 :
xs.reserve(foos.size());
std::transform(foos.begin(), foos.end(), back_inserter(xs), [](Foo f){return f.x;});
또한 x
이 Object
의 개인 회원이며 더 게터이없는 동안, 그것을 추출하는 것은 매우 힘들 것입니다 것을 알 수 있습니다.
정말 좋은 방법이라고 생각할 수 없습니다.
한 가지 대안은 람다와 함께 std::transform
을 사용하는 것입니다.
#include <vector>
#include <algorithm>
class Foo {
public:
Foo(int x_): x(x_) {}
int x;
};
int main() {
std::vector<Foo> foos;
for (int i = 0; i<10; i++) {
foos.push_back(Foo(i));
}
std::vector<int> xs;
xs.resize(foos.size());
std::transform(foos.begin(), foos.end(), xs.begin(), [](Foo f){return f.x;});
}
일부 템플릿과 매크로 마법, 그리고 작동 : 그것은 기능, 또는 생산 using namespace std
쓰기로 물론
#include <vector>
#include <algorithm>
using namespace std;
class Foo {
public:
Foo(int x_): x(x_) {}
int x;
};
#define GETFIELD(type, field) [](const type & obj){return obj.field;}
template<typename T,typename U, typename TMapper>
void MapVector(vector<T>& src, vector<U>& dst, TMapper mapper) {
for (const auto& it: src) {
dst.push_back(mapper(it));
}
}
#define MapVectorField(src, dst, field) MapVector(src, dst, GETFIELD(decltype(src)::value_type, field))
int main() {
vector<Foo> vFoo;
for (int i = 0; i < 10; i++) {
vFoo.push_back(Foo(i));
}
vector<int> vX;
MapVector(vFoo, vX, GETFIELD(Foo, x));
MapVectorField(vFoo, vX, x);
for (int i = 0; i < vX.size(); i++) {
printf("%d\n", vX[i]);
}
}
, 매크로 MapVectorField
이름이 매우 좋지 않다 기억 해요. range-v3와
, 단순히
std::vector<int> xs = objs | ranges::view::transform(&Object::x);
것 또는 바로보기 사용
auto xs = objs | ranges::view::transform(&Object::x);
대신 매크로의 포인터 멤버를 사용할 수 있습니다'& 푸 :: X를 '. – Jarod42