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; }
No comments:
Post a Comment