[/
 / Distributed under the Boost Software License, Version 1.0. (See accompanying
 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 /]

[section Introduction]

Writing STL iterators, views, and containers is surprisingly hard.  There are a
lot of things that can subtly go wrong.  It is also very tedious, which of
course makes it error-prone.

Iterators have numerous typedefs and operations, even though all the
operations of a given iterator can be implemented in terms of at most four
operations (and usually only three).  Writing all the other operations yields
very similar-looking code that is hard to review, and all but requires that
you write full-coverage tests for each iterator.

Writing view types like those found in `std::ranges` is also laborious,
considering that most of each view type's API can be derived from `begin()`
and `end()`.  C++20 has a template that does exactly this,
`std::ranges::view_interface`; _IFaces_ provides a pre-C++20-friendly
implementation.

Due to inconsistencies in the way different compilers implement their C++20
view adaptors' `operator|` support, its particularly thorny to try and write a
view adaptor portable across multiple versions of C++, or even across multiple
compilers building in C++20 mode.  _IFaces_ provides a type
`boost::stl_interfaces::range_adaptor_closure` that is compatible with C++23's
`std::range_adaptor_closure`, and which works with earlier versions of C++ as
well.  _IFaces_ also has helper templates that make it much easier to write
view adaptors with `operator|` support.

Most daunting of all is the task of writing a type or template that meets the
container requirements in the standard.  _IFaces_ provides another template
called _cont_iface_ that reduces the implementation and testing burden
dramatically.

[note C++20 versions of _iter_iface_ and _cont_iface_ are provided (C++20
provides `std::view_interface`).  These are constrained templates using C++20
concepts.  These are in the `boost::stl_interfaces::v2` namespace.  There is
also a C++23 version of _iter_iface_ that uses deducing `this` instead of
_CRTP_.  If you do nothing, you'll get the latest `vN` namespace inlined,
depending on your compiler's language support. ]

[heading A Quick Example]

Here is an example of the iterator portion of the library.  Let's say that we
wanted to make a random access iterator that represents a string of arbitrary
length constructed by repeating a shorter string.  Let's call this iterator
`repeated_chars_iterator`.  Here it is in action:

[repeated_chars_iterator_usage]

There's nothing in the standard library that gets us that kind of behavior, so
we have to write it.  This library seeks to turn what we write from this:

    struct repeated_chars_iterator
    {
        using value_type = char;
        using difference_type = std::ptrdiff_t;
        using pointer = char const *;
        using reference = char const;
        using iterator_category = std::random_access_iterator_tag;

        constexpr repeated_chars_iterator() noexcept :
            first_(nullptr),
            size_(0),
            n_(0)
        {}
        constexpr repeated_chars_iterator(
            char const * first,
            difference_type size,
            difference_type n) noexcept :
            first_(first),
            size_(size),
            n_(n)
        {}

        constexpr reference operator*() const noexcept
        {
            return first_[n_ % size_];
        }

        constexpr value_type operator[](difference_type n) const noexcept
        {
            return first_[(n_ + n) % size_];
        }

        constexpr repeated_chars_iterator & operator++() noexcept
        {
            ++n_;
            return *this;
        }
        constexpr repeated_chars_iterator operator++(int)noexcept
        {
            repeated_chars_iterator retval = *this;
            ++*this;
            return retval;
        }
        constexpr repeated_chars_iterator & operator+=(difference_type n) noexcept
        {
            n_ += n;
            return *this;
        }

        constexpr repeated_chars_iterator & operator--() noexcept
        {
            --n_;
            return *this;
        }
        constexpr repeated_chars_iterator operator--(int)noexcept
        {
            repeated_chars_iterator retval = *this;
            --*this;
            return retval;
        }
        constexpr repeated_chars_iterator & operator-=(difference_type n) noexcept
        {
            n_ -= n;
            return *this;
        }

        friend constexpr bool operator==(
            repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept
        {
            return lhs.first_ == rhs.first_ && lhs.n_ == rhs.n_;
        }
        friend constexpr bool operator!=(
            repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept
        {
            return !(lhs == rhs);
        }
        friend constexpr bool operator<(
            repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept
        {
            return lhs.first_ == rhs.first_ && lhs.n_ < rhs.n_;
        }
        friend constexpr bool operator<=(
            repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept
        {
            return lhs == rhs || lhs < rhs;
        }
        friend constexpr bool operator>(
            repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept
        {
            return rhs < lhs;
        }
        friend constexpr bool operator>=(
            repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept
        {
            return rhs <= lhs;
        }

        friend constexpr repeated_chars_iterator
        operator+(repeated_chars_iterator lhs, difference_type rhs) noexcept
        {
            return lhs += rhs;
        }
        friend constexpr repeated_chars_iterator
        operator+(difference_type lhs, repeated_chars_iterator rhs) noexcept
        {
            return rhs += lhs;
        }
        friend constexpr repeated_chars_iterator
        operator-(repeated_chars_iterator lhs, difference_type rhs) noexcept
        {
            return lhs -= rhs;
        }
        friend constexpr difference_type operator-(
            repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept
        {
            return lhs.n_ - rhs.n_;
        }

    private:
        char const * first_;
        difference_type size_;
        difference_type n_;
    };

(that's a lot of code!) into this:

[repeated_chars_iterator]

Ah, that's better.  Both of these definitions for `repeated_chars_iterator`
have the same semantics and performance profile.  It's just a lot less code to
write the second one, and writing the second one is more novice-friendly.

[note _IFaces_'s `iterator_interface` implements iterators that model the
C++20 iterator concepts.]

[endsect]

[section This Library's Relationship to Boost.Iterator]

_Iterator_ is a library that is already in Boost, and it has been around for a
long time.

However, it was attempting to solve a lot of problems related to iterators,
not just how to write them from scratch.  It is also not easy to modernize it
for use in C++11 and later.  Specifically:

- _Iterator_ contains a large number of iterator adaptors; those have since
  been rendered moot by C++20 ranges.

- _Iterator_'s `iterator_facade` template is not limited just to the
  existing standard C++ iterator categories; that was an experiment that never
  landed in standard C++, so it adds needless complexity.

- _Iterator_'s `iterator_facade` was written against C++98, so it is not
  `constexpr`- and `noexcept`-friendly.

- _Iterator_'s `iterator_facade` does not support proxy iterators, which
  are fully supported by the C++20 iterator concepts.

- There is opportunity to reduce the amount of code the user must write in
  order to use `iterator_facade`.

- _Iterator_ contains two templates, `iterator_facade` and `iterator_adaptor`,
  that represent two ways of writing a new iterator while writing as little
  code as possible.  It would be nice to have the functionality for both
  available in one template, but it is difficult to unify those two templates
  as written.

For these reasons, it seems more appropriate to introduce a new Boost library
than to try and address the shortcomings of _Iterator_'s `iterator_facade` and
`iterator_adaptor` templates directly.

[endsect]

[section The `v1` and `v2` Namespaces, and the Use of C++20 Concepts]

For much of this library, there are two interfaces: one in namespace
`boost::stl_interfaces::v1`, and one in `boost::stl_interfaces::v2`.
The `v1` version uses SFINAE to constrain templates, and the `v2`
version uses concepts, including the standard concepts from C++20.

When you build with a conforming C++20 compiler, the compiler defines
a macro `__cpp_lib_concepts` that indicates that the compiler supports
concepts, and provides the standard concepts in `std` and
`std::ranges`.  When _IFaces_ sees the `__cpp_lib_concepts` macro
defined, it inlines the `v2` namespace; otherwise, it inlines the `v1`
namespace.

The net result for you as a user is that, for some function or type
`foo` with `v1` and `v2` versions, you can use
`boost::stl_interfaces::foo`, and you will get
`boost::stl_interfaces::v1::foo` when building in C++14 or C++17
modes, and `boost::stl_interfaces::v2::foo` when building in C++20 or
later.

If you are using an early C++20 implementation that claims to have
concept support, but that breaks when you build _IFaces_'s C++20 code,
you can disable the `v2` namespace by defining _disable_concepts_m_. ]

[endsect]
