C++20之Ranges

目录

什么是ranges库

Ranges-v3库由Eric Niebler开发的,最初是作为N4128提案的基础,后来合并到C++20。

一个简单的示例

#include <ranges>
std::vector<double> vec{ 1.2, 1.3, 1.4, 3, 5 };
auto result = vec | std::views::filter([](double d) { return d > 1.2; })
	| std::views::transform([](double d) { return d * 2; })
	| std::views::take(2);
for (auto&& v : result) {
	std::cout << v << " ";
}
// output: 2.6 2.8

其中result是一个复杂的view类型,其类型大致如下,编码过程中更建议使用auto进行声明,可读性更佳。

std::ranges::take_view<
    std::ranges::transform_view<
        std::ranges::filter_view<
            std::ranges::ref_view<std::vector<double>>, 
            /* filter lambda 类型 */
        >, 
        /* transform lambda 类型 */
    >, 
    size_t
>

上述功能如果不适用ranges库,大致写法如下:

std::vector<double> nums{};
std::vector<double> filtered{};
std::copy_if(nums.begin(), nums.end(), std::back_inserter(filtered), pred);
std::vector<double> transformed{};
std::transform(...)...

ranges库解决的问题

  1. 传统STL算法需要迭代器和算法配合,读者一定写过不少begin + end的迭代器对,编码时很不友好;
  2. 避免中间容器,上述不使用ranges库的代码中创建临时容器会有一定性能开销;
  3. 惰性求值,view只是一个惰性的试图,只有使用的时候才会计算,可以提高性能;
  4. 函数式编程,ranges提供的管道运算可以实现更直观的数据流,更加贴近函数式编程;

源码分析(MSVC)

前置知识concept

源码解读

#define _RANGES ::std::ranges::
_EXPORT_STD template <class _Ty>
concept view = range<_Ty> && movable<_Ty> && enable_view<_Ty>;

_EXPORT_STD template <class _Rng, class _Ty>
concept output_range = range<_Rng> && output_iterator<iterator_t<_Rng>, _Ty>;

_EXPORT_STD template <class _Rng>
concept forward_range = range<_Rng> && forward_iterator<iterator_t<_Rng>>;

_EXPORT_STD template <class _Rng>
concept random_access_range = range<_Rng> && random_access_iterator<iterator_t<_Rng>>;

_EXPORT_STD template <class _Rng>
concept range = requires(_Rng& __r) {
    _RANGES begin(__r);
    _RANGES end(__r);
};

Tags: #C++