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

multiset<IMidiMsgExt, IMidiMsgExtCompByNoteNumber> playingNotes;


例如当我使用.find()函数时,它将搜索并返回具有该NoteNumber属性值的第一个对象(迭代器)。

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

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

我会误会整个事情吗?怎么了?

最佳答案

我相信您在这里有一些误解:


associative container类型的一部分是键类型和比较器。因为C ++是强类型的,所以更改容器上比较器的唯一方法是创建一个新容器,将所有元素复制或移动到其中
在容器中创建所有元素的副本是一个潜在的昂贵过程
通过创建副本,您违反了Single Source of Truth最佳做法
multiset很少使用,我在职业生涯中使用过一次,其他人指出了它的缺点,建议您使用use another containerwrite 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



  我想删除具有60个mNote的第一个音符。无论删除时的mTime。



您需要捕获[find_if]的结果,检查它是否有效,如果erasemy answer中所示,对它进行验证,因为you say



  找到的第一个元素将为此找到并擦除。 [原文]



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



  我想起来是否想删除另一个元素(可能具有相同的值)被删除[病]


最终的解决方案应该是编写一个如下所示的函数:

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的返回值。

10-01 14:32