Skip to content
/ radr Public

C++ 𝗥ange 𝗔𝐝aptors 𝗥eimagined

License

Notifications You must be signed in to change notification settings

h-2/radr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

📡 C++ ℝange 𝔸𝕕aptors ℝeimagined (radr)

This library explores an opinionated re-design of C++ Range Adaptors, commonly referred to as "views". It tries to reduce complexity in the conceptual space and provide a better, more consistent user experience. At the same time, the usage patterns and naming remain close enough to the standard library to be used almost as a drop-in replacement.

🪞 Differences and similarities to std::ranges

auto adapted_range  =  original_range  |  range_adaptor_object  |  range_adaptor_object2;

The general pattern for creating adapted ranges is the same in our library and in the standard library. However, we aim to establish clearer rules for what you can and cannot do with the adapted_range. To achieve this, we are sometimes stricter about what the original_range needs to provide.

⌨️ Summary for the casual C++ programmer

🤓 Summary for the Ranges nerd

This library fundamentally differentiates between multi-pass and single-pass ranges.

  1. multi-pass ranges:
  • Adaptors return one of two class templates: radr::owning_rad or radr::borrowing_rad for owning/borrowing ranges respectively.
  • The semantics are implemented completely in terms of an iterator-sentinel pair which is always stored/cached.
  • This means adaptors on borrowed ranges are also borrowed ranges, and no "view" concept is required.
  • Adaptors never contain mutable state, are always const-iterable and calling .begin() (non-const) has no side effects.
  1. single-pass ranges:
  • Adaptors on single-pass ranges always return a std::generator.
  • This results in simpler types, fewer nested template instantiations, and avoids lots of special cases in the multi-pass implementations.

📖 Further reading

Please have a look at the docs folder. In particular, you may be interested in:

  • Getting started: short introduction on how to use this library and the terminology used in the documentation.
  • Implementation status: overview of which adaptors are already available.
  • Examples: examples that illustrate standard library usage vs radr usage ("tony tables").
  • Trade-offs: things to be aware before switching to this library.

🗒️ Library facts

  • Easy to use: header-only and no dependencies
  • License: Apache with LLVM exception1
  • Compilers: GCC≥11 or Clang≥17
  • Standard libraries: both libstdc++ and libc++ are tested.
  • C++20 required.2

👪 Credits

Not everything presented here is novel—in fact, many of the ideas are based on older "ranges" designs (e.g. old ISO papers, Boost ranges and old range-v3). One "innovation" is applying different rules to multi-pass and single-pass ranges, and one important decision is opting out of the whole "What is a view" discussion.

This library uses code from the standard library implementation of the LLVM project. It also uses a draft implementation of std::generator from https://github.com/lewissbaker/generator.

I want to thank various members of the DIN AK Programmiersprachen for thoughtful discussions on the topic.

Footnotes

  1. The file generator.hpp is licensed under the Boost Software license. It is used only if your standard library does not provide std::generator.

  2. A bonus of using this library is getting access to the equivalent of C++23 and C++26 adaptors in a C++20-based codebase.