【问题标题】:Force foreach to use const iterators强制 foreach 使用 const 迭代器
【发布时间】:2013-11-25 06:06:16
【问题描述】:

我有一个自定义容器类,它实现了cbegin()cend() 函数。然后我在foreach循环中使用它,但它似乎需要begin()end()成员函数,即使我尝试使用const修饰符:

for (const auto val: container)

像这样:

for (auto const val: container)

像这样:

for (const auto const val: container)

是否可以强制 foreach 使用常量 c 函数?

【问题讨论】:

  • 不,它只使用beginend。如果对 const 对象进行操作,只需创建 beginend 函数返回 const_iterator
  • @chris 但是如果我们想constly 迭代一个可变对象呢?我们必须做演员吗?
  • @uk4321,我相信标准容器也存在同样的问题。
  • 您知道代码中的it 实际上不是迭代器,而是迭代器包含的类型的实例?你可能想说for (const auto& inst : container)
  • @kfsone 是的,这是真的。谢谢,我已经更新了代码。但就我而言,它只是一个整数。

标签: c++ c++11 iterator containers


【解决方案1】:

当然:让范围看起来好像是const 范围:

template <typename T>
T const& make_const(T const& argument) {
    return argument;
}

// ...
for (auto&& value: make_const(argument)) {
    ...
}

然而,在所有情况下,基于范围的for 将使用begin()end(),而从不使用cbegin()cend()。您可能想提供这些:

template <typename T>
auto begin(my_container<T> const& t) -> decltype(t.cbegin()) {
    return t.cbegin();
}
template <typename T>
auto end(my_container<T> const& t) -> decltype(t.cend()) {
    return t.cend();
}

显然,您希望将my_container 替换为合适的容器类型。就个人而言,我可能只会提供合适的begin()end() 成员。

【讨论】:

    【解决方案2】:

    我不确定只提供cbegin()cend() 的决定是什么,但这些并没有在基于范围内使用。如果您想在基于您的范围内使用您的容器需要提供begin()end()(尽管您可以让它们返回 const 迭代器)

    【讨论】:

    • 原因是将容器突变限制为几个函数。
    • @Max,您可以为此提供const_iterator begin() const,就像std::set 一样
    • 我明白这一点。 STL 使用以 c 为前缀的函数来使 constness 显式化,而 foreach 只能与隐式 constness 一起使用,这似乎很奇怪。
    • @Max: cbegincend 是 C++11 的新手,所有 C++11 之前的容器只有 beginend,通常有两个重载每个,用于 const 和非 const 对象。奇怪的情况是容器不提供beginend,但提供cbegincend。当所有(除了您的)容器共享相同的接口时,无需支持基于范围的使用cbegincend
    【解决方案3】:

    您应该始终在 两个 重载中提供 begin()/end() 函数,一个 const 和一个非常量。新的cbegin()/cend() 函数的目的是允许使用auto 进行推断,如:

    for (auto it = v.cbegin(); it != v.cend(); ) { /* ... */ }
    

    如果没有新函数,您只能在此处获取非 const 迭代器(或插入一个非常尴尬的转换)。

    【讨论】:

    • ty - 提供两个重载对我来说非常有用 - 在过去的一个小时里,我一直在努力思考为什么 range-based-for 不会使用 cbegin()/cend() .
    猜你喜欢
    • 2019-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-04
    相关资源
    最近更新 更多