Thursday, October 20, 2011

make_range_raw

I wrote a range library some years ago and then found a proposal to include a range library in the std library.

I adopted the proposed library and over time I have added additional features to ease usage of C APIs. One feature I added is make_range_raw.

make_range works by requiring that the Range passed in has support for the begin and end free-functions. This produces range<Iterator> where Iterator is a raw pointer for built-in arrays but uses the iterator type defined by the Range when it is a collection like vector or wstring. This is the desired behavior for make_range but when trying to interface between collections and C APIs it would be better to access the raw pointer for contiguous array collections like vector and wstring.

make_raw_range requires that the collection support raw access via operator []. Using &r[0] for begin and &r[0] + size(r) for end produces range<Iterator> where Iterator is always a raw pointer. (for well behaved collections this is true. vector<bool> is not well behaved)

Implementation

maintained here

template< class Range >
auto
make_range_raw(Range && r) ->
decltype(
  make_range(
      &r[0],
      &r[0] + size(r)
  )
)
{
  if (size(r) == 0) {
    decltype(
      make_range(
          &r[0],
          &r[0] + size(r)
      )
    ) result;
    return result;
  }
  return make_range(
      &r[0],
      &r[0] + size(r)
      );
}

template< class Range >
auto
make_range_raw(
  Range && r,
  typename
  range_difference<Range>::type advance_begin,
  typename
  range_difference<Range>::type advance_end
) ->
decltype(
  make_range(
      &r[0],
      &r[0] + size(r)
  )
)
{
  decltype(
    make_range(
        &r[0],
        &r[0] + size(r)
    )
  ) result;
  if (size(r) != 0) {
    result = make_range(
        &r[0],
        &r[0] + size(r)
        );
  }
  result.advance_begin(advance_begin);
  result.advance_end(advance_end);
  return result;
}

No comments:

Post a Comment