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:
- use a sorted vector (sorted by timestamp) as my 'set'.
- this allows me to search in logarithmic time, same as a set
- but I can now search across the set quickly (no pointer de-referencing and good cache locality)
code:
#include <vector>
#include <algorithm>
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<midi_message> _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);
}