【问题标题】:C++/STL public iterators for deeply nested private data用于深度嵌套私有数据的 C++/STL 公共迭代器
【发布时间】:2017-05-14 04:46:20
【问题描述】:

考虑以下具有深度嵌套私有数据的类定义。

template <typename T, typename U, typename V>
class NestedData {
private:
  typedef std::vector<V> L3;
  typedef std::map<U, L3> L2;
  typedef std::map<T, L2> L1;
  L1 inner_data;
};

假设我们希望添加一个公共接口来迭代三个级别中的每一个。也就是说,我们希望允许客户端构建三个嵌套循环,这些循环遍历类型 V 的每个值,知道类型 U 和 T 的关联值。我们可以添加以下方法:

L1::const_iterator begin() const { return inner_data.begin(); }
L1::const_iterator end() const { return inner_data.end(); }

在这种情况下,迭代器的结果将是对的,右侧被引用到类型 L2。尽管引用是 const,但它公开了 std::map 类型的完整 API,这对于公共接口来说是不可取的。一个更简洁的解决方案将只提供一个包装器,以使迭代 L2 成为可能。但是,我还没有看到任何用于这种 STL 容器封装的标准习惯用法,即使是最好的情况,解决方案的实现似乎也会造成高度的代码膨胀。

对于这个问题,有什么通用的解决方案可以很好地适应通用 C++ 约定?

【问题讨论】:

  • 我想知道您是否想重新考虑您的数据结构以减少它们的“嵌套”...

标签: c++ class stl iterator


【解决方案1】:

只需通过const getter 公开地图本身。公开迭代器仍会将您的用户绑定到底层数据类型,但它会削弱他们 - 例如,他们不能在其上使用 find - 因此存在一个没有任何好处的缺点。

如果您可以重新设计您的类,使内部映射完全成为一个实现细节,并且客户永远不需要看到它 - 那么您将删除迭代器和设置器,并公开一些有意义的函数。

【讨论】:

  • +1 - 此外,通过 const ref 公开地图,如果您的客户在迭代时正确使用 auto,即使您的数据结构更改了他们的代码也不需要。
  • 公开map 的整个API,甚至是map 的细节,对于接口来说都是不受欢迎的。我正在寻找实现充分封装的方法。
  • 通过公开地图迭代器,您正在公开地图本身。你没看到吗?
  • 我愿意。我在最初的问题中说我这样做了,而这种观察是问题的核心目的的基础。在封装特定容器选择的同时公开数据的首选习惯用法是什么?
【解决方案2】:

我将创建一个自定义迭代器,它会在您迭代时提供 T、U、V 值。这将使您的用户与数据的实现细节完全隔离。如果您确实需要嵌套类型逻辑。然后我会使用一个自定义迭代器,它返回一个适配器对象,它将最终的迭代器返回到列表中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-03
    • 2016-04-30
    • 2012-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-19
    相关资源
    最近更新 更多