我建议升级。如果这不是一个选项,我只能看到一个在以下情况下有效的助手实现
-
您有一个临时键值,但您知道它不在容器中
-
或者,您可以使用不需要密钥提取器的密钥提取器
unique_ptr
非空
我将使用选定的INVKEY演示第一个选项
-1
(0xFFFFFFFF)作为临时“删除”键:
template <typename Idx, typename V = Idx::value_type> V extract(Idx& idx, size_t key) {
auto it = idx.find(key);
if (it == idx.end())
return nullptr;
BasePtr tmp = std::make_unique<Derived>(Base::INVKEY);
idx.modify(it, [&tmp](BasePtr& element) { //
element.swap(tmp);
});
idx.erase(it);
return tmp;
}
请注意,它优雅地返回
nullptr
当钥匙找不到的时候。这可能是也可能不是你想要的
演示程序
Live On Coliru
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/tag.hpp>
#include <boost/multi_index_container.hpp>
#include <memory>
#include <vector>
#include <fmt/ranges.h>
struct Base {
static constexpr size_t INVKEY = -1ul;
virtual size_t GetId() const = 0;
virtual ~Base() = default;
};
using BasePtr = std::unique_ptr<Base>;
struct Derived : Base {
Derived(size_t id) : id_(id) {}
size_t GetId() const override { return id_; }
private:
size_t id_;
};
template <> struct fmt::formatter<Base, char> : fmt::formatter<size_t> {
auto format(Base const& b, auto& ctx) const { return fmt::format_to(ctx.out(), "{}", b.GetId()); }
};
template <typename T> struct fmt::formatter<std::unique_ptr<T>, char> : fmt::formatter<std::decay_t<T>> {
auto format(std::unique_ptr<T> const& p, auto& ctx) const {
if (p)
return fmt::format_to(ctx.out(), "{}", *p);
else
return fmt::format_to(ctx.out(), "(nullptr)");
}
};
using ContainerType = boost::multi_index_container<
BasePtr,
boost::multi_index::indexed_by<
boost::multi_index::sequenced<boost::multi_index::tag<struct Sequenced>>,
boost::multi_index::hashed_unique<boost::multi_index::tag<struct Ordered>,
boost::multi_index::const_mem_fun<Base, size_t, &Base::GetId>> //
>>;
template <typename Idx, typename V = Idx::value_type> V extract(Idx& idx, size_t key) {
auto it = idx.find(key);
if (it == idx.end())
return nullptr;
BasePtr tmp = std::make_unique<Derived>(Base::INVKEY);
idx.modify(it, [&tmp](BasePtr& element) { //
element.swap(tmp);
});
idx.erase(it);
return tmp;
}
int main() {
ContainerType container;
fmt::print("Initial: {}\n", container);
// Insert an element.
auto& ordered = container.get<Ordered>();
{
auto [it, inserted] = ordered.insert(std::make_unique<Derived>(42));
assert(inserted);
}
{
auto [it, inserted] = ordered.insert(std::make_unique<Derived>(99));
assert(inserted);
}
fmt::print("Inserted: {}\n", container);
for (size_t key : {42u, 123u, 99u}) {
BasePtr extracted = extract(ordered, key);
fmt::print("Extracted for key {}: {}, remain {}\n", key, extracted, container);
}
}
印刷品
Initial: {}
Inserted: {42, 99}
Extracted for key 42: 42, remain {99}
Extracted for key 123: (nullptr), remain {99}
Extracted for key 99: 99, remain {}
确认
Compiler Explorer Boost 1.73.0