range copy
The range library proposal for the std library included copy_range
which required that the dest range have a constructor that took begin and end iterators. This was not applicable to C struct ranges like UNICODE_STRING
.
I decided to fix this by following the pattern for the begin
and end
free-functions. A free-function named copy
calls a free-function named range_copy
via ADL that can be overloaded for each Range type. The default range_copy
has the same behavior that the proposed copy_range
provided, but now other range_copy
overloads can be written.
UNICODE_STRING
usage
This snippet shows some of the operations now enabled.
auto helloRange = as_literal(L"hello");
auto title = copy<std::wstring>(helloRange);
auto unicodeHello = copy<UNICODE_STRING>(helloRange);
auto stringRange = make_range(unicodeHello);
auto unicodeTitle = copy<UNICODE_STRING>(
make_range_raw(title)
);
stringRange = make_range(unicodeTitle);
- line 1 will make a
range<const wchar_t*>
that points to the static string array. - line 2 will make a
std::wstring
that holds a copy of the static string array. - line 4 will make a
UNICODE_STRING
that points to the static string array. - line 5 will make a
range<PWSTR>
that points to the static string array. - line 6 will make a
UNICODE_STRING
that points to thewstring
copy of the static string array. - line 9 will make a
range<PWSTR>
that points to thewstring
copy of the static string array.
Implementation
maintained here
template< class RangeTo, class RangeFrom >
auto range_copy(RangeFrom && r, RangeTo*) ->
decltype(
RangeTo(
begin(std::forward<RangeFrom>(r)),
end(std::forward<RangeFrom>(r))
)
)
{
return RangeTo(
begin(std::forward<RangeFrom>(r)),
end(std::forward<RangeFrom>(r))
);
}
template< class RangeTo, class RangeFrom >
auto copy(RangeFrom && r) ->
decltype(
range_copy(
std::forward<RangeFrom>(r),
reinterpret_cast<RangeTo*>(nullptr)
)
)
{
return range_copy(
std::forward<RangeFrom>(r),
reinterpret_cast<RangeTo*>(nullptr)
);
}
line 27 passes in a nullptr
cast to a RangeTo*
this dummy parameter is ugly but required to enable Argument-Dependent-Lookup (ADL) when range_copy
is implemented in RangeTo
's namespace. I considered using the parameter rather than returning a RangeTo
by-value, but then RangeTo
must be default-constructable since the copy
free-function would have to have one on the stack in order to pass a pointer into range_copy
. The current definition allows the overload for RangeTo
to use any constructor.
UNICODE_STRING
implementation
Now enabling UNICODE_STRING
for use with the range library requires only this
// enable UNICODE_STRING <-> range
PWSTR range_begin(const UNICODE_STRING& string)
{
return string.Buffer;
}
PWSTR range_end(const UNICODE_STRING& string)
{
return string.Buffer + (string.Length / 2);
}
template< class RangeFrom >
UNICODE_STRING range_copy(
RangeFrom && r,
UNICODE_STRING*
)
{
UNICODE_STRING result = {};
result.Buffer = const_cast<PWSTR>(
begin(std::forward<RangeFrom>(r))
);
result.Length = size_cast<USHORT>(
size(std::forward<RangeFrom>(r)) * 2
);
result.MaximumLength = size_cast<USHORT>(
size(std::forward<RangeFrom>(r)) * 2
);
return result;
}