这个问题涉及:
When should I use the new ranged-for and can I combine it with the new cbegin/cend?
基于该问题,强制使用cbegin()
和cend()
,需要做的事情,例如:
for (auto& v: const_cast<decltype(container) const>(container))
这是一个应该消除它的构造的很多样板代码。有更紧凑的方法吗?我的问题的原因是,隐式共享容器可能会使用begin()
作为分离自己的线索。
答案 0 :(得分:27)
更新:std::as_const
将位于<utility>
标题中的C ++ 17中。
在C ++ 17 之前,它没有内置语法;但是,您可以轻松编写便利包装器:
template<typename T> constexpr const T &as_const(T &t) noexcept { return t; }
for (auto &v: as_const(container))
请注意,这会特别调用begin() const
而不是cbegin()
; Standard container general requirements指定cbegin()
和begin() const
的行为相同。
如果你的容器特别处理非常量迭代,那么它本身就有一个成员函数是有意义的:
const Container &crange() const noexcept { return *this; }
for (auto &v: container.crange())
答案 1 :(得分:11)
const auto& const_container = container;
for (const auto& v: const_container ) {
答案 2 :(得分:3)
基于范围的for循环从不使用cbegin()
或cend()
。 (因此没有办法强迫它。)令人惊讶的是有许多相反的谣言;有些人认为使用cbegin()
和cend()
,但从不尝试在没有begin()
和end()
的情况下编译相同的代码。一个简单的例子如下。据推测,无论添加了多少begin
,都只会打印end
和const_cast
。
#include <iostream>
class Iterable {
struct Iterator {
bool operator !=(const Iterator &) { return false; }
int operator *(){ return 0; }
Iterator& operator ++() { return *this; }
};
public:
Iterator cbegin() const noexcept {
std::cout << "cbegin" << std::endl;
return Iterator{};
}
Iterator cend() const noexcept {
std::cout << "cend" << std::endl;
return Iterator{};
}
Iterator begin() const noexcept {
std::cout << "begin" << std::endl;
return Iterator{};
}
Iterator end() const noexcept {
std::cout << "end" << std::endl;
return Iterator{};
}
};
int main() {
Iterable a;
const Iterable b;
for (auto i : a) {}
for (auto i : b) {}
for (const auto &i : a) {}
for (const auto &i : b) {}
return 0;
}