1

この作業コードを検討してください。この関数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*valueObject*searchByDataMember

4

1 に答える 1

2

operator ->*連続して申請する方法が必要です。

template <typename T, typename MPtr>
auto arrow(T* obj, MPtr mptr)
{
    return obj->*mptr;
}

template <typename T, typename MPtr, typename ... MPtrs>
auto arrow(T* obj, MPtr mptr, MPtrs... mptrs)
{
    return arrow(obj->*mptr, mptrs...);
}

次に、検索関数は次のような単純なものです:(ところで、値よりもイテレータを返すことを好みます)

template <typename Container, typename T, typename... DataPtrs>
auto searchByDataMember (const Container& container, const T& t, DataPtrs... ptrs)
{
    return std::find_if(std::begin(container), std::end(container),
                [&](const auto&e) {
                    return arrow(e, ptrs...) == t;
                });
}

デモ

于 2015-11-18T22:37:28.587 に答える