0

我正在将 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());

我可以使用接口或模板方法让“任何类”部分工作,但还没有找到如何使“任何方法”部分工作。

有没有办法做类似于 C++ 中的“d => d.GetId()” lambda(有或没有 Boost)?

替代的,更多使算法通用的 C++ian 解决方案也受到欢迎。

我在 VS2008 中使用 C++/CLI,所以我不能使用 C++0x lambdas。

4

2 回答 2

6

假设,我了解您要查找的内容,您可以使用boost::bind

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

实际上,您只需要boost::mem_fnor std::mem_fun,但boost::bind会让您更加通用。

在这种情况下,您可以定义FindNonUniqueValues为:

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

在这里,我不太确定你是如何FindNonUniqueValues获得它的对象列表的(或者它应该返回的究竟是什么——IEnumerable就像一个迭代器?),所以你可以填写它。

于 2010-05-01T19:44:58.500 回答
2

以供将来参考,这是我在遵循已接受答案的想法后得出的解决方案:

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")
于 2010-05-02T00:03:54.337 回答