c++ - Comparator 可以用来设置新的 key ,不是吗?

标签 c++ stl iterator comparator

我需要更改多重集的“键”:

multiset<IMidiMsgExt, IMidiMsgExtCompByNoteNumber> playingNotes;

例如当我使用 .find() 时它的功能是搜索并返回带有 NoteNumber 的第一个对象(迭代器)适当的值(value)。

我说“第一”是因为我的多重集列表可能包含具有相同“键”的对象。所以我做了:

struct IMidiMsgExtCompByNoteNumber {
    bool operator()(const IMidiMsgExt& lhs, const IMidiMsgExt& rhs) {
        return lhs.NoteNumber() < rhs.NoteNumber();
    }
};

但是当我尝试这样做时:

auto it = playingNotes.find(60);

编译器说 no instance of overloaded function "std::multiset<_Kty, _Pr, _Alloc>::find [with _Kty=IMidiMsgExt, _Pr=IMidiMsgExtCompByNoteNumber, _Alloc=std::allocator<IMidiMsgExt>]" matches the argument list

我是不是误解了整件事?怎么了?

最佳答案

我相信你对这里有一些误解:

  1. associative container 的一部分的类型是它的键类型和比较器。因为 C++ 是强类型的,所以更改容器上的比较器的唯一方法是创建一个新容器,将所有元素复制或移动到其中
  2. 创建容器中所有元素的拷贝可能是一个代价高昂的过程
  3. 创建拷贝即违反了 Single Source of Truth最佳实践
  4. multiset 很少用,职业生涯用过一次,别人指出了不足,推荐给大家use another container , write your own container ,或者就我而言,我建议只使用 vector 并在必要时按您想要的方式对其进行排序

我将对您的评论进行分类以展示如何 the answer I've already given you是正确的:

  • 我们假设 multiset<IMidiMsgExt, IMidiMsgExtCompByNoteNumber>您选择的是必需的,无法使用 vector 进行改进如 4 中所建议,其中:
struct IMidiMsgExtCompByNoteNumber {
    bool operator()(const IMidiMsgExt& lhs, const IMidiMsgExt& rhs) {
        return lhs.NoteNumber() < rhs.NoteNumber();
    }
};
  • 您不能使用 multiset::find 因为这需要您指定确切的 IMidiMsgExt您正在寻找;所以你需要使用 find_if(cbegin(playingNotes), cend(playingNotes), [value = int{60}](const auto& i){return i.mNote == value;})搜索特定属性值。在 PlayingNotes 上直接使用哪个会很好不改变排序,因为you say :

I want to delete the first note that has mNote of 60. No matter the mTime when deleting.

  • 您需要捕获 [ find_if 的结果], 检查它是否有效,如果有效 erasemy answer 所示,因为 you say :

The first element find will find for that, erase. [sic]

  • 我会将答案中的代码滚动到一个函数中,因为 you say :

Ill recall find if I want another element, maybe with same value, to get deleted [sic]

您的最终解决方案应该是编写如下函数:

bool foo(const multiset<IMidiMsgExt, IMidiMsgExtCompByNoteNumber>& playingNotes, const int value) {
    const auto it = find_if(cbegin(playingNotes), cend(playingNotes), [=](const auto& i){return i.mNote == value;});
    const auto result = it != cend(playingNotes);

    if(result) {
        playingNotes.erase(it);
    }
    return result;
}

你会这样调用它:foo(playingNotes, 60)如果你想知道一个元素是否被删除,你可以测试 foo的返回。

关于c++ - Comparator 可以用来设置新的 key ,不是吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36920853/

相关文章:

c++ - 我可以抛出一个 unique_ptr 吗?

arrays - 反循环缓冲区

符合 c++ STL 的迭代器迭代器

c++ - 比较给定宽度和高度的纵横比

c++ - 在 Linux (GCC 4.6) 上聚集 C++ ifstream

c++ - 如果模板模板参数是 vector ,则需要不同的行为

c++ - 我需要有人向我解释这些代码行

Javascript:当字符串连接时,新的正则表达式会破坏 for 循环迭代器

c++ - 右值参数无法在函数重载中解析

php - 在 Javascript 之后获取 HTML - 服务器应用程序