Templates and generic programming
T.24
Use tag classes or traits to differentiate concepts that differ only in semantics.
Reason
Two concepts requiring the same syntax but having different semantics lead to ambiguity unless the programmer differentiates them.
Example
template<typename I> // iterator providing random access
// Note: random_access_iterator is defined in <iterator>
concept RA_iter = ...;
template<typename I> // iterator providing random access to contiguous data
// Note: contiguous_iterator is defined in <iterator>
concept Contiguous_iter =
RA_iter<I> && is_contiguous_v<I>; // using is_contiguous trait
The programmer (in a library) must define is_contiguous (a trait) appropriately.
Wrapping a tag class into a concept leads to a simpler expression of this idea:
template<typename I> concept Contiguous = is_contiguous_v<I>;
template<typename I>
concept Contiguous_iter = RA_iter<I> && Contiguous<I>;
The programmer (in a library) must define is_contiguous (a trait) appropriately.
Note
Traits can be trait classes or type traits. These can be user-defined or standard-library ones. Prefer the standard-library ones.
Enforcement
- The compiler flags ambiguous use of identical concepts.
- Flag the definition of identical concepts.