#include <algorithm>
#include <iostream>
#include <list>

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;
                });
}

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) {}
};


int main() {
    Thing thing1(5, 6, "Sam");
    Object o1(8, &thing1);
    Thing thing2(11, 7, "Mark");
    Object o2(8, &thing2);
    Thing thing3(9, 12, "Rob");
    Object o3(8, &thing3);
    Thing thing4(2, 11, "Tom");
    Object o4(8, &thing4);
    std::list<Object*> objects{&o1, &o2, &o3, &o4};

    const auto it = searchByDataMember (objects, 11, &Object::thing, &Thing::value);
    std::cout << (*it)->thing->name << '\n';  // Tom (the desired output)
}