How can I set two kind of comparator (one for insert, one for find) on this multiset?

后端 未结 4 1762
忘了有多久
忘了有多久 2021-01-23 14:48

I have declared this STL multiset:

multiset playingNotes;

and my comparator is:



        
4条回答
  •  庸人自扰
    2021-01-23 15:04

    What you want to do is not possible (while keeping the logarithmic search properties of the map). The reason is that the find method takes an instance of key_type, so even writing a custom comparator which has overloads for comparing your key_type against ints will not work.

    The idea of a key_type is that it's an immutable and cheap object to construct - i.e. you should be unafraid to treat it as a value that can be copied.

    Edit:

    Here's how I may approach it.

    Synopsis:

    1. use a sorted vector (sorted by timestamp) as my 'set'.
    2. this allows me to search in logarithmic time, same as a set
    3. but I can now search across the set quickly (no pointer de-referencing and good cache locality)

    code:

    #include 
    #include 
    
    struct midi_message
    {
      midi_message(int timestamp, int note) 
        : _timestamp(timestamp)
        , _note(note)
        {}
      int timestamp() const { return _timestamp; }
      int note() const { return _note; }
    private:
      int _timestamp, _note;
    };
    
    struct earlier
    {
      bool operator()(const midi_message& l, const midi_message& r) const {  
        return l.timestamp() < r.timestamp();
      }
    
      bool operator()(const midi_message& l, const int& r) const {  
        return l.timestamp() < r;
      }
    };
    
    struct midi_messages
    {
      // insert messages, keeping the map sorted by timestamp
      void add(midi_message m) {
        auto i = std::lower_bound(std::begin(_data),
                                      std::end(_data),
                                      m.timestamp(),
                                      earlier());
    
        _data.insert(i, std::move(m));
      }
    
      bool remove_first_note_like(int note)
      {
        auto i = std::find_if(std::begin(_data), 
                              std::end(_data),
                              [note](auto& msg) 
                              { return msg.note() == note; });
        if (i != std::end(_data)) {
          _data.erase(i);
          return true;
        }
        return false;
      }
    
      std::size_t remove_all_before(int timestamp)
      {
        auto new_begin = std::lower_bound(std::begin(_data),
                                          std::end(_data),
                                          timestamp,
                                          [](auto& msg, auto& timestamp) {
                                            return msg.timestamp() < timestamp;
                                          });
        _data.erase(std::begin(_data), new_begin);
      }
    
      private:
      std::vector _data;
    };
    
    int main()
    {
      midi_messages messages;
    
      messages.add(midi_message(1000, 60));
      messages.add(midi_message(1000, 60));
      messages.add(midi_message(1000, 60));
      messages.add(midi_message(1001, 60));
      messages.add(midi_message(1002, 70));
      messages.add(midi_message(1002, 60));
      messages.remove_first_note_like(60);
      messages.remove_all_before(1001);
    }
    

提交回复
热议问题