| Home | Libraries | People | FAQ | More

## Rationale

#### There Are Minimal Derived-Type Constraints

This is the constraint on the `Derived` template parameter to `iterator_interface`, `view_interface` and `sequence_container_interface`:

    std::enable_if_t<
        std::is_class<Derived>::value &&
        std::is_same<Derived, std::remove_cv_t<Derived>>::value>

This prevents instantiating an interface template with an `int`, a `const` type, a reference type, etc.

Further constraints are not possible (for instance, that `view_interface` is given a `Derived` template parameter for a type that has a `begin()` and `end()`), because `Derived` is an incomplete type within each *`_interface` template.

#### Using a Special Access-Granting `struct`

The interface templates rely mostly on public members provided by their `Derived` template parameter. However, `iterator_interface` requires you to supply `base_reference()` functions if you want it to act like an adaptor. Since at least the non-`const` overload provides a non-`const` lvalue reference to one of your types data members, it will break the encapsulation of many types to leave `base_reference()` a public member. To allow users to keep these overloads private, `access` exists.

#### `iterator_interface` Can Act Like an Adaptor, And the Other Interface Templates Can't

There wouldn't be much point in adding this functionality to `view_interface`, because it only uses the `begin()` and `end()` of the `Derived` type anyway.

For `sequence_container_interface` it also does not make much sense. Consider how many container adaptors you've written. That's a use case that does not come up often.

#### `iterator_interface` Takes a Lot of Template Parameters, And the Other Interface Templates Don't

`iterator_interface` does in fact take a lot of template parameters. However, it usually only takes three: the `Derived` type, the iterator category, and the iterator's `value_type`.

When you make a proxy iterator, you typically use the `proxy_iterator_interface` alias, and you again only need the same three template parameters. Though you can opt into more template parameters, the rest are seldom necessary.

By contrast, the `view_interface` and `sequence_container_interface` templates have very few template parameters. For `view_interface`, this is because there are no member typedefs in the `view` concept. For `sequence_container_interface`, it was deemed ridiculous to create a template whose purpose is to reduce code size, which takes 14 template parameters.

#### `sequence_container_interface` Does not Deduce Nested Types Like `iterator`

`sequence_container_interface` could deduce some of the nested types required for a standard sequence container. For instance, `iterator` can be deduced as `decltype(*begin())`. However, a type `D` derived from `sequence_container_interface` may need to use some of these nested types — like `iterator` — in its interface or implementation. If this is the case, those nested types are not available early enough in the parse to be used in `D`, if they come from deductions in `sequence_container_interface`. This leaves the user in the awkward position of defining the same nested type with a different name that can be used within `D`. It seems better to leave these types for the user to define.

#### `sequence_container_interface` Does not Support Associative or Unordered Associative Containers

That's right. Associative containers have an interface that assumes that they are node-based containers. On modern hardware, node-based containers are not very efficient, and I don't want to encourage people to write more of them. Unordered associative containers have an interface that precludes open addressing. I don't want to encourage more of that either.

#### `sequence_container_interface` Does not Satisfy the Allocator-Aware Container Requirements

It may not be immediately obvious, but `sequence_container_interface` simply cannot help with the allocator-aware requirements. All of the allocator-aware requirements but 3 are special members and constructors. A CRTP base template is unable to provide those, based on the language rules. That leaves the `allocator_type` typedef, which the user must provide; member `swap()`, which is already a container requirement (the allocator-aware table entry just specifies that member `swap()` must be constant-time); and `get_allocator()`, which again is something the user must provide.

Most of the difficulty of dealing with allocators has to do with the implementation details of their use within your container. `sequence_container_interface` provides missing elements of a sequence container's interface, by calling user-provided members of that same interface. It cannot help you with your container's implementation.