この作業コードを検討してください。この関数searchByDataMember
は、データ メンバーへのポインターを引数として使用して、コンテナー内の値を検索します。
#include <iostream>
#include <list>
#include <string>
template <typename Container, typename T, typename DataPtr>
typename Container::value_type searchByDataMember (const Container& container, const T& t,
DataPtr ptr) {
for (const typename Container::value_type& x : container) {
if (x->*ptr == t)
return x;
}
return typename Container::value_type{};
}
struct Object {
int ID, value;
std::string name;
Object (int i, int v, const std::string& n) : ID(i), value(v), name(n) {}
};
std::list<Object*> objects { new Object(5,6,"Sam"), new Object(11,7,"Mark"),
new Object(9,12,"Rob"), new Object(2,11,"Tom"), new Object(15,16,"John") };
int main() {
const Object* object = searchByDataMember (objects, 11, &Object::value);
std::cout << object->name << '\n'; // Tom
}
では、それ自体を指しているデータ メンバーが検索するデータ メンバーを持っている場合に、データ メンバーへのポインターの可変長リストを引数として使用するように上記を拡張するにはどうすればよいでしょうか。例えば、
#include <iostream>
#include <list>
#include <string>
template <typename Container, typename T, typename... DataPtrs>
typename Container::value_type searchByDataMember (const Container& container, const T& t,
DataPtrs... ptrs) {
// What to put here???
}
struct Thing {
int ID, value;
std::string name;
Thing (int i, int v, const std::string& n) : ID(i), value(v), name(n) {}
};
struct Object {
int rank;
Thing* thing;
Object (int r, Thing* t) : rank(r), thing(t) {}
};
std::list<Object*> objects { new Object(8, new Thing(5,6,"Sam")), new Object(2, new Thing(11,7,"Mark")),
new Object(1, new Thing(9,12,"Rob")), new Object(9, new Thing(2,11,"Tom"))};
int main() {
// The desired syntax.
// const Object* object = searchByDataMember (objects, 11, &Object::thing, &Thing::value);
// std::cout << object->thing->name << '\n'; // Tom (the desired output)
}
ここでは、データ メンバが 11のデータ メンバを 持つ をコンテナ内objects
で検索します。これは、 "Tom" を持つ です。に渡すことができるデータ メンバーへのポインターのチェーンの大きさに制限はありません。Object*
Thing*
value
Object*
searchByDataMember