Boost lambda: вызов метода для объекта - PullRequest
0 голосов
/ 01 мая 2010

Я рассматриваю boost :: lambda как способ создания универсального алгоритма, который может работать с любым методом "getter" любого класса.

Алгоритм используется для обнаружения повторяющихся значений свойства, и я хотел бы, чтобы оно работало для любого свойства любого класса.

В C # я бы сделал что-то вроде этого:

class Dummy
{
    public String GetId() ...
    public String GetName() ...
}

IEnumerable<String> FindNonUniqueValues<ClassT>
  (Func<ClassT,String> propertyGetter) { ... }

Пример использования метода:

var duplicateIds   = FindNonUniqueValues<Dummy>(d => d.GetId());
var duplicateNames = FindNonUniqueValues<Dummy>(d => d.GetName());

Я могу заставить работать часть "любого класса", используя интерфейсы или шаблоны, но пока не нашел, как заставить работать часть "для любого метода".

Есть ли способ сделать что-то похожее на лямбду "d => d.GetId ()" в C ++ (с Boost или без)?

Альтернатива, приветствуются и другие решения на C ++ ian, чтобы сделать алгоритм универсальным.

Я использую C ++ / CLI с VS2008, поэтому я не могу использовать лямбды C ++ 0x.

Ответы [ 2 ]

6 голосов
/ 01 мая 2010

Если я понимаю, что вы ищете, вы можете использовать boost::bind:

FindNonUniqueValues<Dummy>(boost::bind(&Dummy::GetId, _1));

На самом деле вам просто нужно boost::mem_fn или даже std::mem_fun, но boost::bind позволит вам немного больше общности.

В этом случае вы бы определили FindNonUniqueValues как что-то вроде:

template <typename T>
/* ? */ FindNonUniqueValues(boost::function<std::string (const T&)> getter) { ... }

Здесь я не совсем уверен, как ваш FindNonUniqueValues получает свой список объектов (или точно, что он должен возвращать - это IEnumerable как итератор?), Так что вы можете заполнить это. *

2 голосов
/ 02 мая 2010

Для дальнейшего использования, вот решение, которое я закончил, после следующих идей из принятого ответа:

template < typename ObjectT, typename ValueT > std::vector <ObjectT>
FindInstancesWithDuplicateValue(
   vector<ObjectT> allValues, mem_fun_ref_t<ValueT, ObjectT> getter)
{ 
    // [...create a *sorted* list of  ObjectT, ordered by ObjectT.getter()...]
    // [...loop through the sorted list to find identical adjacent values...]
        // call the mem_fun_ref_t:
        ValueT value1 = getter(*iterPrev);
        ValueT value2 = getter(*iter);
        if (value1 == value2) // duplicates found
    // ...
}

Пример использования:

vector<Dummy> list;
list.push_back(Dummy(1, "1-UniqueValue"));
list.push_back(Dummy(2, "2-DuplicateValue"));
list.push_back(Dummy(3, "2-DuplicateValue"));
list.push_back(Dummy(4, "3-UniqueValue"));

vector<Dummy> dummyWithduplicateNames = 
    FindInstancesWithDuplicateValue<Dummy,CString>
    (list, mem_fun_ref(&Dummy::GetName));

// returns Dummy(2, "2-DuplicateValue") and Dummy(3, "2-DuplicateValue")
...