2009-07-16 13 views
0

ベクトルからデータを取得するための一般的な方法が必要です。一般的な検索方法ですか?

私は次のクラスとベクトルがあります。

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

この例では、私は、ベクター内のオブジェクトを取得できるようにしたいと思いますが"FindDataById"に似た2つの関数を書く必要なく、 "z"または "foo"メンバーに基づいています。

これは可能ですか?

+0

、それが簡単に人々が疑問を読み取るために作るためにあなたのコードの一部を挿入します。 – jalf

答えて

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の答えを参照してください。テンプレートを推論する方法引数を自動的に取得しました。 、今

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

そして:

+0

"Finder"ビットが機能せず、テンプレートパラメータがありません。私のコードを参照してテンプレート引数の減算を行う方法。 – MSalters

+0

それを行うための別の(おそらくあまりエレガントでない)方法を提供するために編集されました。 – Ari

+0

文字列( "名前")はもう必要ありません。 – MSalters

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

      ..... 

} 
0

それはSTD見てみる価値があるかもしれない::アルゴリズムで定義されていて、後押し見つける::ラムダ

1

std::find_ifは、既に提案されているが、コードサンプルなしで、ので、ここではより詳細なバージョンです:

はあなたが興味を持っているオブジェクトを識別するために、2つのファンクタを定義するには、ラムダのなし

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

あなたには、いくつかの述語、またはでを記述する必要があると思います:Z == 42.0f、またはFOO ==「Hello Worldのは」要素を検索します少なくともそれらをインスタンス化します。

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

関連する問題