【问题标题】:Associative array with multiple keys types, possible?具有多种键类型的关联数组,可能吗?
【发布时间】:2010-12-29 23:20:45
【问题描述】:

我有一大堆对象(可能有 1000 个)需要存储在一个容器中。我需要能够通过两种方式找到特定实例,或者通过它的 ID 号(64 位无符号整数)或它的名称(std::string)。通常通过 ID 是最常见的,但在某些情况下,名称是已知的,而不是 ID。

std::map 可以提供单个 值,但是我不确定是否有 2 组 std::map 容器,一组用于 Id,另一组用于字符串是这里的最佳方法。

编辑 - 修改代码和错误:

好的,我想我会尝试使用多索引,因为无论如何我都有提升,但是即使我已经完成它与文档中的完全相同,我似乎也无法编译它我可以告诉:(

测试代码:

namespace common
{
    class MyBaseClass
    {
    public:
        typedef boost::uint64_t Id;

        //name and id are constant, at least for the period im intrested in
        //when I want it in the container...
        const std::string &getName()const{return name;}
        Id getId()const{return id;}

        ...other stuff...
    };
}

class MyClass : public common::MyBaseClass
{
    ...other stuff...
};

typedef boost::multi_index_container
<
    MyClass*,
    boost::indexed_by
    <
        boost::ordered_unique<boost::const_mem_fun<MyBaseClass, MyBaseClass::Id,    &MyBaseClass::getId  > >,
        boost::ordered_unique<boost::const_mem_fun<MyBaseClass, const std::string&, &MyBaseClass::getName> >
    >
>MyClassList;

还有你的平均提升模板错误...

c:\lib\c++\boost\boost\aligned_storage.hpp(69):错误 C2872:'detail':不明确的符号
可能是'boost::detail'
或 'boost::multi_index::detail'
c:\lib\c++\boost\boost\multi_index\detail\index_node_base.hpp(42) :请参阅正在编译的类模板实例化“boost::aligned_storage”的参考

[
尺寸_=4,
对齐_=4
]
c:\lib\c++\boost\boost\multi_index\detail\index_node_base.hpp(47) :请参阅正在编译的类模板实例化 'boost::multi_index::detail::pod_value_holder' 的参考

[
价值=我的班级 *
]
c:\lib\c++\boost\boost\multi_index\detail\ord_index_node.hpp(582) :请参阅正在编译的类模板实例化 'boost::multi_index::detail::index_node_base' 的参考

[
值=我的班级 *,
分配器=std::分配器
]
c:\lib\c++\boost\boost\multi_index\ordered_index.hpp(137) :请参阅正在编译的类模板实例化 'boost::multi_index::detail::ordered_index_node' 的参考

[
Super=boost::multi_index::detail::index_node_base>
]
c:\lib\c++\boost\boost\multi_index\ordered_index.hpp(119) :请参阅正在编译的类模板实例化“boost::multi_index::detail::ordered_index”的参考

[
KeyFromValue=boost::multi_index::const_mem_fun,
比较=std::less,std::allocator>>,
SuperMeta=boost::multi_index::detail::nth_layer,boost::multi_index::ordered_unique>>,std::allocator>,
TagList=boost::mpl::vector0,
类别=boost::multi_index::detail::ordered_unique_tag
]
c:\lib\c++\boost\boost\multi_index_container.hpp(86) : 请参阅正在编译的类模板实例化 'boost::multi_index::detail::ordered_index' 的参考

[
KeyFromValue=boost::multi_index::const_mem_fun,
比较=std::less,
SuperMeta=boost::multi_index::detail::nth_layer,boost::multi_index::ordered_unique>>,std::allocator>,
TagList=boost::mpl::vector0,
类别=boost::multi_index::detail::ordered_unique_tag
]
c:\projects\bad_angle_studios\brak3\trunk\source\source\server\MyClass.cpp(18) :请参阅正在编译的类模板实例化“boost::multi_index::multi_index_container”的参考

[
值=我的班级 *,
IndexSpecifierList=boost::multi_index::indexed_by>,boost::multi_index::ordered_unique>>
]
c:\lib\c++\boost\boost\aligned_storage.hpp(53) : 错误 C2872: 'detail' : 不明确的符号
可能是'boost::detail'
或 'boost::multi_index::detail'
c:\lib\c++\boost\boost\aligned_storage.hpp(56) :请参阅正在编译的类模板实例化“boost::detail::aligned_storage::aligned_storage_imp::data_t”的参考

[
尺寸_=4,
对齐_=4
]
c:\lib\c++\boost\boost\aligned_storage.hpp(69) :请参阅正在编译的类模板实例化“boost::detail::aligned_storage::aligned_storage_imp”的参考

[
尺寸_=4,
对齐_=4
]
c:\lib\c++\boost\boost\aligned_storage.hpp(73) : 错误 C2872: 'detail' : 不明确的符号
可能是'boost::detail'
或 'boost::multi_index::detail'
c:\projects\bad_angle_studios\brak3\trunk\source\source\server\MyClass.cpp(44) : error C2676: binary '[' : 'MyClassList' 未定义此运算符或转换为预定义可接受的类型运营商

【问题讨论】:

  • 很抱歉,我的笔记本电脑上没有开发环境。如果在 typedef'ing MyClassList 时使用 common::MyBaseClass 而不是 MyClass ,它会编译吗?
  • 好的,我将其更改为基类并使其使用“cosnt std::string&”,但是现在我得到一个不同的错误...
  • 好的,我编辑了主要帖子以反映他的更改和新错误

标签: c++ containers associative-array


【解决方案1】:

boost::multi_index 是您问题的答案。有关如何使用它的更多信息,请参阅there

【讨论】:

    【解决方案2】:

    两个映射的方法(一个以 ID 为键,第二个以名称为键)对我来说似乎很好。它易于实现,并且运行良好。

    我看到其他答案推荐了 boost 库。如果您已经在项目中使用了 boost,那么它可能是一个很好的解决方案。如果您不这样做 - 我不确定是否值得为您的项目添加提升,只是为了这个简单的案例。

    【讨论】:

    • 请注意:当您只需要有限数量的 boost 库时,您可以使用名为 bcp 的简单工具提取它们。这样,即使在 boost 内,您也无需为不需要的东西付费。
    【解决方案3】:

    您可以将数据存储在 std::vector 中并使用 std::find 算法来查找您的项目。查找算法接受不同的比较器,因此只需定义一个匹配 ids 和另一个匹配名称的比较器。

    find 算法比 std::map 和 std::set 的 find 方法慢,所以如果性能是一个大问题,那么你最好用空间换取速度,要么使用 2 个地图,要么使用 boost

    编辑,刚刚想到。将数据存储在地图中,使用 id 作为键,因为这是常见的情况。然后使用 std::find 算法和与不常见情况下的名称匹配的谓词。这应该会减少(但不会消除)性能问题

    【讨论】:

    • "slower" 是轻描淡写,std::find 是一个简单的 O(n) 前向搜索。如果您关心优化查找时间,则不应使用它。
    • @Terry,是的,我知道。但是 OP 没有提到性能要求,所以我指出了它们的可能性
    【解决方案4】:

    这是上述方法的另一种选择,您选择哪种解决方案取决于您的需求。 Grab SqlLite 将有关对象的数据存储在数据库中并为它们运行查询。

    【讨论】:

      【解决方案5】:

      Fire Lancer,你没有正确限定 Boost.MultiIndex 名称,而不是例如 boost::indexed_by 你必须写 boost::multi_index::indexed_by 等等。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-06-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多