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::wstringthat holds a copy of the static string array. - line 4 will make a
UNICODE_STRINGthat 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_STRINGthat points to thewstringcopy of the static string array. - line 9 will make a
range<PWSTR>that points to thewstringcopy 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;
}
No comments:
Post a Comment