通用查找方法?

时间:2009-07-16 12:30:00

标签: c++ templates vector

我想要一个从向量中检索数据的通用方法。

我有以下类和矢量:

class myClass
{
    public:

    myClass(int myX, float myZ, std::string myFoo)
        : x ( myX )
        , z ( myZ )
        , foo ( myFoo )
    {

    }
    myClass()
    {

    }

    int x;
    float z;
    std::string foo;

} ;
std::vector < myClass > myVector;

(完整的代码可以在这里看到:http://codepad.org/iDD1Wme5

在这个例子中,我希望能够基于“z”或“foo”成员检索向量中的对象,而不必编写类似于“FindDataById”的另外两个函数。

这可能吗?

5 个答案:

答案 0 :(得分:4)

您可以使用模板和指向成员的指针。

typedef vector<myClass> myVector;

template<typename T>
bool FindDataById(const T &id, T myClass::* idMember, myClass &theClass,
                                                       const myVector &theVector)
{
   for(myVector::const_iterator itr = theVector.begin(); itr != myVector.end();
                                                                          ++itr){
       if((*itr).*idMember == id){
          theClass = *itr;
          return true;
   }

   return false;
}

然后使用例如

进行呼叫
FindDataById(string("name"), &myClass::foo, theClass, theVector)
FindDataById(5, &myClass::x, theClass, theVector)
FindDataById(5.25f, &myClass::z, theClass, theVector)

或者,请使用find_if想法:

template<typename T>
struct Finder {
   T val_;
   T myClass::* idMember_;

   Finder(T val, T myClass::* idMember) : val_(val), idMember_(idMember) {}
   bool operator()(const myClass &obj) { return obj.*idMember_ == val_; }
};

并使用:

find_if(theVector.begin(), theVector.end(), Finder<string>("name", &myClass::foo))
find_if(theVector.begin(), theVector.end(), Finder<int>(5, &myClass::x))
find_if(theVector.begin(), theVector.end(), Finder<float>(3.25f, &myClass::z))

请参阅MSalters的答案,了解自动推断模板参数的方法。

答案 1 :(得分:1)

已经建议

std::find_if,但没有代码示例,所以这里是更详细的版本:

定义两个仿函数来识别您感兴趣的对象:

struct z_equals {
  z_equals(float z) : z(z) {}

  bool operator()(const myClass& obj)
    return z == obj.z;
  }

  float z;
};


struct foo_equals {
  foo_equals(const std::string& foo) : foo(foo) {}

  bool operator()(const myClass& obj)
    return foo == obj.foo;
  }

  const std::string& foo;
};

现在,要搜索z == 42.0f或foo ==“hello world”的元素:

std::find_if(myVector.begin(), myVector.end(), z_equals(42.0f));
std::find_if(myVector.begin(), myVector.end(), foo_equals("hello world"));

答案 2 :(得分:0)

您可以使用仿函数并将其传递给查找方法。我的意思是,定义将重载bool operator( vectorElement element)的类,在此运算符中,您将选择方法如何查找值。

template <typename T>
class ILookUp
{
    bool operator( vector<T> elem)
    {
      if (elem == something)
          return true;
      false;
    }
};

class VectorStorage
{
     std::vector<Elements> lookup( ILookUp<Elements> lookup)
     {

         .....         

         if ( lookup(elem))
         {
              //add element to vector or whatever.
         }

          .....

         return result;
     }

          .....

}

答案 3 :(得分:0)

值得一看的是在算法和boost :: lambda

中定义的std :: find

答案 4 :(得分:0)

如果没有lambda,你需要编写一些谓词,或至少实例化它们:

template
struct member_select : public std::unary_function
{
  T t;
  T U::* m_u;
  member_select(T const& t, T U::* m_u) : t(t), m_u(m_u) {}
  bool operator()(U const& u) const { return u.*m_u == t; }
};

template
member_select make_member_select(T const& t, T U::* m_u)
{
  return member_select(t, m_u);
}

使用:std::find_if(..., make_member_select("x", &myClass::foo));

相关问题