gpt4 book ai didi

c++ - 如何将 boost::intrusive_ptr 与 boost::intrusive::list 一起使用?

转载 作者:行者123 更新时间:2023-12-02 10:28:18 28 4
gpt4 key购买 nike

我想一次准确地分配一个对象并将其推送到几个列表中。如何使用 boost::intrusive_ptr 执行此操作和 boost::intrusive::list ?或者我应该使用另一个容器和引用计数器?

最佳答案

侵入式列表和 intrusive_ptr 不相关。

  • 一个来自 "Boost Intrusive" library
  • 另一个是来自 "Boost SmartPtr" library 的智能指针

  • 可以使用任何一个。侵入式容器具有更多管理功能,但需要 dedicated hook每个容器。 intrusive_ptr更灵活,因为它可以通过使用引用计数来支持无界容器。
    此外,请记住,如果您只想对相同的基础数据进行多个索引,通常您可以使用 Boost MultiIndex 并获得两全其美的效果。
    侵入性列表
    最简单的演示: Live On Compiler Explorer
    #include <string>
    #include <boost/intrusive/list.hpp>
    #include <boost/intrusive/list_hook.hpp>

    // for debug output
    #include <fmt/ranges.h>

    namespace bi = boost::intrusive;

    using BaseHook = bi::list_base_hook<>;
    using MemberHook = bi::list_member_hook<>;

    struct Item : BaseHook {
    std::string data;
    Item(std::string data) : data(std::move(data)) {}

    MemberHook _secondary, _secondary2;

    bool operator<(Item const& rhs) const { return data < rhs.data; }
    };

    template <> struct fmt::formatter<Item> : fmt::formatter<std::string> {
    template <typename Ctx>
    auto format(Item const&val, Ctx &ctx) { return fmt::format_to(ctx.out(), "'{}'", val.data); }
    };

    // primary container uses the base hook
    using Items = bi::list<Item>;
    using Secondary = bi::list<Item, bi::member_hook<Item, MemberHook, &Item::_secondary >>;
    using Third = bi::list<Item, bi::member_hook<Item, MemberHook, &Item::_secondary2 >>;

    int main() {
    Item elements[] { {"one"}, {"two"}, {"three"} };

    Items primary(std::begin(elements), std::end(elements));

    Secondary idx1(primary.begin(), primary.end());
    Third idx2(primary.begin(), primary.end());

    idx1.sort();
    idx2.reverse();

    fmt::print("primary: {}\n", primary);
    fmt::print("idx1: {}\n", idx1);
    fmt::print("idx2: {}\n", idx2);
    }
    打印
    primary: {'one', 'two', 'three'}
    idx1: {'one', 'three', 'two'}
    idx2: {'three', 'two', 'one'}
    使用 intrusive_ptr请注意,这是如何更加动态的,但因此成本更高。另请注意,由于容器元素不再是“直接值”,所有操作都因为间接而变得更加复杂:
  • 插入需要动态分配(new)
  • sort 需要一个谓词,以免您在指针
  • 上进行排序
  • 打印需要间接

  • I used various other Boost helpers to save time here, but note that this kind of complexity might reduce your development speeds more depending on whether you know these helper bits


    Live On Compiler Explorer
    #include <string>
    #include <boost/intrusive_ptr.hpp>
    #include <boost/smart_ptr/intrusive_ref_counter.hpp>
    #include <list>

    // helpers to make handling containers of intrusive pointers easier
    #include <boost/range/adaptor/indirected.hpp>
    #include <boost/ptr_container/indirect_fun.hpp>
    #include <memory>

    // for debug output
    #include <fmt/ranges.h>

    struct Item : boost::intrusive_ref_counter<Item> {
    std::string data;
    Item(std::string data) : data(std::move(data)) {}

    bool operator<(Item const& rhs) const { return data < rhs.data; }
    };

    template <> struct fmt::formatter<Item> : fmt::formatter<std::string> {
    template <typename Ctx>
    auto format(Item const&val, Ctx &ctx) { return fmt::format_to(ctx.out(), "'{}'", val.data); }
    };

    int main() {
    using List = std::list<boost::intrusive_ptr<Item> >;

    List primary;
    for (auto name : {"one","two","three"}) {
    primary.emplace_back(new Item(name));
    }

    List idx1(primary.begin(), primary.end());
    List idx2(primary.begin(), primary.end());

    idx1.sort(boost::make_indirect_fun(std::less<Item>{}));
    idx2.reverse();

    fmt::print("primary: {}\n", primary | boost::adaptors::indirected);
    fmt::print("idx1: {}\n", idx1 | boost::adaptors::indirected);
    fmt::print("idx2: {}\n", idx2 | boost::adaptors::indirected);
    }
    打印
    primary: {'one', 'two', 'three'}
    idx1: {'one', 'three', 'two'}
    idx2: {'three', 'two', 'one'}
    奖励:多索引容器
    你没有要求这个,但给定样本似乎是一个合乎逻辑的解决方案(我意识到样本可能不代表你的问题,当然):
    Live On Compiler Explorer
    #include <string>
    #include <boost/multi_index_container.hpp>
    #include <boost/multi_index/sequenced_index.hpp>

    // for debug output
    #include <fmt/ranges.h>

    struct Item {
    std::string data;
    bool operator<(Item const& rhs) const { return data < rhs.data; }
    };

    template <> struct fmt::formatter<Item> : fmt::formatter<std::string> {
    template <typename Ctx>
    auto format(Item const&val, Ctx &ctx) { return fmt::format_to(ctx.out(), "'{}'", val.data); }
    };

    namespace bmi = boost::multi_index;
    using Table = bmi::multi_index_container<Item,
    bmi::indexed_by<
    bmi::sequenced<>, // primary
    bmi::sequenced<bmi::tag<struct Index1> >,
    bmi::sequenced<bmi::tag<struct Index2> >
    > >;

    int main() {
    Table primary{ {"one"},{"two"},{"three"} };

    auto& idx1 = primary.get<Index1>();
    auto& idx2 = primary.get<Index2>();

    idx1.sort();
    idx2.reverse();

    fmt::print("primary: {}\n", primary);
    fmt::print("idx1: {}\n", idx1);
    fmt::print("idx2: {}\n", idx2);
    }
    打印
    primary: {'one', 'two', 'three'}
    idx1: {'one', 'three', 'two'}
    idx2: {'three', 'two', 'one'}
    后者具有 - 迄今为止 - 最大的灵 active 和最高级别的语义(例如,删除元素适用于所有索引)。您可以拥有关联索引、有序键、复合键等。在这种情况下,它们将在 replace 上自动维护。或 modify .
    当然,如果您的用例不像固定集合的索引,那么您可能需要第一个选项。

    关于c++ - 如何将 boost::intrusive_ptr 与 boost::intrusive::list 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63356373/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com