我想要一个从向量中检索数据的通用方法。
我有以下类和矢量:
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”的另外两个函数。
这可能吗?
答案 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));