几乎总是自动和带计数器的循环

Almost Always Auto and for loops with counter

本文关键字:计数器 循环      更新时间:2023-10-16

Herb Sutter 状态几乎总是自动的,我有以下代码:

using count_t = int;
count_t get_count() { ... };
const auto count = get_count();
for (decltype(count) i = 0; i < count; i++) {
// Do the stuff
}

从本质上讲,使用decltype()允许我编写一个可以使用任何整数类型的 for 循环(希望get_count()永远不会返回浮点数(,而无需对函数get_count()客户端代码进行任何修改,并避免编译警告,如"有符号-无符号"不匹配。

我的问题是:假设count_t将来可能会被重新定义,这种形式是否可以接受?

如果可以选择使用Boost,则可以避免所有噪音

#include <boost/range/irange.hpp>
for(auto i : boost::irange(get_count()))

boost::irange的单参数版本是在 1.68 中引入的,因此您需要复制早期版本的实现。

要仍然是 AAA,您可以转到:

for (auto i = decltype(count){}; i != count; ++i) { /*..*/ }
template<class T>
struct indexer_t {
T t;
T operator*()const{return t;}
void operator++(){++t;}
friend bool operator==(indexer_t const& lhs, indexer_t const& rhs) {
return lhs.t==rhs.t;
}
friend bool operator!=(indexer_t const& lhs, indexer_t const& rhs) {
return lhs.t!=rhs.t;
}
};
template<class It>
struct range_t {
It b,e;
It begin() const { return b; }
It end() const { return e; }
};
template<class T>
range_t<indexer_t<T>> count_over( T const& s, T const& f ) {
return { {s}, {f} };
}
template<class T>
range_t<indexer_t<T>> count_upto( T const& t ) {
return count_over<T>( 0, t );
}
for (auto i : count_upto(count))
{
// Do the stuff
}

indexer_trange_t可以改进;它们都是最小的实现。

这是另一种选择。我不会宣布它比你自己的建议更好或更差:

for (auto i = 0 * count; i < count; i++) {

请注意,如评论中所述,在count类型小于int的情况下,这与您的行为不同,在这种情况下,我的i被提升。

也就是说,基于索引的循环通常(也许总是?(可以转换为基于迭代器的循环,其中auto推导更自然。