Implementing ranges

TODO write a tutorial and lots of information about implementing your own range.

template <class Expression>
struct callable_traits::result_of

Compute the result of a call expression, as a typedef type.

If the expression is invalid, then do not contain type at all.

template <class Expression>
struct callable_traits::has

Boolean constant that indicates whether a function call expression is valid.

Iff compiling the call succeeds, value == true.

template <class Range>
struct range::tag_of

Evaluate the range tag of the type Range. The tag should not depend on the qualifier.

tag_of should be used to retrieve the range tag for a type. To assign tags to ranges, it is easiest to specialise tag_of_qualified.

template <class Range>
struct range::tag_of_qualified

Helper for tag_of. Specialise this for an unqualified range to assign it a tag.

Implementing intrinsics



template <class Wrapper>
auto get_underlying(typename std::remove_reference< Wrapper >::type & wrapper)

Return the first argument’s “underlying_” attribute of type Wrapper::underlying_type.

This differentiates between reference and const reference, and rvalues, and returns a similarly qualified reference. The template argument Wrapper must be given, and must have the correct qualification (except ). This works exactly the same as the template parameter to std::forward. 99% of the time, this function would be passed std::forward<...>(...) so this makes that unnecessary.

This allows underlying_ and ::underlying_type to be private:

template <class Wrapper> friend class helper::callable::get_underlying;

  • Wrapper -

    The qualified type of the parameter is passed in.

template <class Wrapper>
struct range::helper::underlying_type
template <class Direction>
class range::helper::with_direction

Ranges often have to hold directions; but they should not take up unnecessary space. This class compresses empty Direction objects by deriving from the Direction class.

template <class Direction>
class range::helper::with_default_direction

Hold a Direction object (and optimise space if it is empty). Additionally, implement default_direction to return that direction.

To implement a range that holds its default direction, simply derive from this class.

template <class First, class Rest>
class range::chopped

Result type for chop, which contains the first element of a range, and the rest of the range. This class is extremely simple. It is assignable if First and Rest are assignable. This is also the case if First is a reference type, a function type, or an array.

  • First -

    The type of the first element of a range. This will often be the exact return type of first().

  • Rest -

    The type of the rest of the range. This will often be an unqualified value.

Implementing a view on a heavyweight range

struct range::operation::heavyweight_tag

Tag for heavyweight objects that can be used as ranges.

Heavyweight ranges are converted to a view, either explicitly, with view() or make_view() or explicitly, by calling empty(), first(), drop(), et cetera.

To allow a heavyweight container to be converted to a view, give the heavyweight container a range tag that derives from heavyweight_tag. first(), for example, will then automatically be implemented for heavyweight h as first (view (h)).

Then, implement the following operations:

  • implement_make_view for all combinations of directions that the range supports.
  • All relevant operations for the view.

Table Of Contents

Previous topic

Computing hashes

This Page