开发者

C++ STD::find_if using structure predicate

 key_struct kStruct;
 kStruct.x = 2;
 std::find_if(m_cueCommands.begin(), m_cueCommands.end(), find_MyInt(kStruct));

 struct key_struct
 {
   int x;
   string y;
   string z;
 }

 struct find_myInt : std::unary_function<key_struct, bool>
 {     
    int  x;     
    find_myInt(key_struct kStruct):myInt(kStruct.x){}     
    bool operator()(key_struct const& m) const
    {         
     return m.x == myInt;     
    }
 };

I am pretty sure I have this a bit messed up but, I think it is moderatly close. What I am trying to do I have the key_struct as the key in my map. I would like to be able to search the keys and return the information that I setup the key_struct 开发者_运维技巧with. If I set the key_struct with x = 2 then I only want to return where the int x is equal to 2. If I set where x = 2 and y = "testString" then I would like to return only the subset of values where x = 2 and y = "testString".

I believe my approach is close but, I think I am missing something. Ideas?


Do you always want to compare with x? Or only if x != 0?

Btw, there seems to be an error in your struct constructor: there is no member named myInt, thus it should be: find_myInt(key_struct kStruct) : x(kStruct.x){}. But that doesn't matter, it needs to be changed anyway.

Here's what I would try. This is untested, might contain errors and the "calculation" of the boolean return value is extremely inefficient. Anyway...

To use it, create a struct you want to match with, as you can see from the code, it will only try to match if x > 0, y != "" and z != "". So if you set the "search" struct to x = 5, y = "" and z = "", it will match every key for which x == 5 (y & z can be whatever).

typedef std::pair<key_struct, your_value_type> yourMapType;

struct find_myStruct : std::unary_function<key_struct, bool>
{
  private:
    key_struct myStruct;

  public:
    find_myInt(key_struct const & kStruct): myStruct(kStruct) {}

    bool operator() (yourMapType const & m) const
    {
      bool result = true;

      if (myStruct.x > 0)
        result &= (myStruct.x == m.first.x);

      if (myStruct.y != "")
        result &= (myStruct.y == m.first.y);

      if (myStruct.z != "")
        result &= (myStruct.z == m.first.z);

      return result;
    }
};

[Edit] Noticed you want to use a map, so I update the code accordingly. Still very much untested, feel free to point out errors.

[Edit 2] In case you have problems actually creating the map, because you don't have strict weak ordering on your key_struct, then this should do.

Again, untested, might contain errors. Also pretty inefficient with all the if's, but well... feel free to get them out with your favourite Karnaugh map solver (BMin comes to mind).

struct cmp_key_struct
{
  bool operator() (key_struct const & lhs, key_struct const & rhs) const
  {
    bool result = (lhs.x < rhs.x);

    if ((!result) && (lhs.x == rhs.x))
    {
      result = (lhs.y < rhs.y);

      if ((!result) && (lhs.y == rhs.y))
        result = (lhs.z < rhs.z);
     }

     return result;
  }
};

std::map<key_struct, your_value_type, cmp_key_struct> yourMap;


This is corrected version :

 struct find_myInt : std::unary_function<key_struct, bool>
 {     
    int  myInt;     /// HERE
    find_myInt(key_struct kStruct):myInt(kStruct.x){}     
    bool operator()(key_struct const& m) const
    {         
     return m.x == myInt;     
    }
 };


You do not need to use find_if on a map. If you are trying to use the struct as a map key, as you said, you need a comparison that provides "strict weak ordering". Use "<" instead of "==", for instance. Then provide that comparison to the map. Or overload the < operator in your struct. You can use the [] operator or the find() method of map to do O(log n) searches, where find_if is O(n).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜