Skip to content

<ranges>, <xutility>: Extract _Strategy to simplify code #1419

@StephanTLavavej

Description

@StephanTLavavej

The Ranges code in <ranges> and <xutility> has a commonly-repeated pattern, where metaprogramming is driven by a chosen "strategy". The code looks like this:

STL/stl/inc/ranges

Lines 830 to 834 in 2b4cf99

if constexpr (_Choice<_Rng>._Strategy == _St::_View) {
return _STD forward<_Rng>(_Range);
} else if constexpr (_Choice<_Rng>._Strategy == _St::_Ref) {
return ref_view{_STD forward<_Rng>(_Range)};
} else if constexpr (_Choice<_Rng>._Strategy == _St::_Subrange) {

STL/stl/inc/xutility

Lines 1088 to 1092 in 2b4cf99

if constexpr (_Choice<_Ty1, _Ty2>._Strategy == _St::_Custom) {
iter_swap(static_cast<_Ty1&&>(_Val1), static_cast<_Ty2&&>(_Val2));
} else if constexpr (_Choice<_Ty1, _Ty2>._Strategy == _St::_Swap) {
_RANGES swap(*static_cast<_Ty1&&>(_Val1), *static_cast<_Ty2&&>(_Val2));
} else if constexpr (_Choice<_Ty1, _Ty2>._Strategy == _St::_Exchange) {

Repeating things like _Choice<_Rng>._Strategy and _Choice<_Ty1, _Ty2>._Strategy for each if constexpr branch is verbose and hard to read. (It's also slightly prone to error; if we keep saying _Choice<_Ty&>._Strategy, we might forget the & somewhere.)

When I implemented the Spaceship CPOs in <compare>, I used an easy way to simplify the code - extracting a constexpr variable. This looks like:

STL/stl/inc/compare

Lines 392 to 395 in 2b4cf99

constexpr _St _Strat = _Choice<_Ty1&, _Ty2&>._Strategy;
if constexpr (_Strat == _St::_Adl) {
return static_cast<strong_ordering>(/* ADL */ strong_order(_Left, _Right));
} else if constexpr (_Strat == _St::_Floating) {

This technique doesn't eliminate all verbosity (any occurrences in requires or noexcept can't use the variable), but it's a strict improvement. I think we should apply this to the <ranges> and <xutility> code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementSomething can be improvedfixedSomething works now, yay!rangesC++20/23 ranges

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions