基于范围的循环 C++11 for range(L,R)

7

C++11没有为范围整数序列提供基于范围的循环。

for(auto e : {0..10} )  // wouldn't compile!!!

所以我决定模拟它。
template< class T , bool enable = std::is_integral<T>::value >
struct range_impl
{
    struct iterator
    {
        constexpr T operator * ()const noexcept { return value; }
        iterator& operator ++()noexcept { ++value; return *this; }

        friend
        constexpr bool operator != (const iterator & lhs, const iterator rhs ) noexcept
        {
            return lhs.value != rhs.value;
        }
        T value;
    };

    constexpr iterator begin()const noexcept { return { first }; }
    constexpr iterator end  ()const noexcept { return { last  }; } 

    T first;
    T last ;
}; 




template< class T >
range_impl<T>  range(T first , T last) noexcept
{
    return {first, last};
}

int main(){
     // print numbers in [ 0..10 ), i.e. 0 1 2 3 4 5 6 7 8 9
     for(auto e : range(0,10) ) std::cout << e <<  ' ';
     std::cout << std::endl;
}

问:如何将这种方法推广到前向迭代器?

示例:

template< class ForwardIterator, class T >
bool find(ForwardIterator first, ForwardIterator last, T const& value)
{
     for(auto e: range(first, last) ) if (e == v) return true;
     return false;
}

3
这并不是过于概括了;整数并非迭代器。你基本上是在创建一个具有相同名称的新函数。 - Nicol Bolas
2个回答

6

专业化

template< class Iterator>
struct range_impl<Iterator, false>
{
    range_impl(Iterator first, Iterator last)
    : first(first), last(last)
    {}

    constexpr Iterator begin()const noexcept { return { first }; }
    constexpr Iterator end  ()const noexcept { return { last  }; }

    Iterator first;
    Iterator last ;
};

测试:

int main(){
     for(auto e : range(0,10) ) std::cout << e <<  ' ';
     std::cout << std::endl;
     const char* a[] = { "Say", "hello", "to", "the", "world" };
     for(auto e : range(a, a + 5) ) std::cout << e <<  ' ';
     std::cout << std::endl;
}

你也可以移除基于整数的范围实现。相反,创建一个整数迭代器,并将其传递给基于迭代器的范围实现(减少代码重复!)。我个人实现的另一件事是,如果迭代器是随机访问的,它会有条件地定义size[],而我的整数迭代器是随机访问的。 - Yakk - Adam Nevraumont

1

对于这种情况,使用auto e : temporaryObject{}的循环,标准是什么?也就是说,可以保证循环结束后temporaryObject的生命周期已经结束了吗? - Khurshid Normuradov
我删除了这段文字。我部分地犯了错误。请参见此处:https://dev59.com/qWkw5IYBdhLWcg3wx9aC - Sebastian
@KhurshidNormuradov 是的,它会结束。范围for循环的语义是清晰的(您可以搜索示例实现),以及在其中创建的临时对象的生命周期也是如此(绑定到引用的临时对象的生命周期是该引用的生命周期)。 - Yakk - Adam Nevraumont

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接