STL: Finish replacing tag dispatch with if constexpr (original) (raw)

Tag dispatch is the STL's original metaprogramming technique: overload a helper function on a tag struct (e.g. input_iterator_tag versus forward_iterator_tag, or true_type versus false_type) and then call it with a tag object to select the appropriate overload. This has several downsides, though - it is somewhat verbose, it interferes with code organization, and it results in actual function calls in debug mode. (This is slower, more work to step through when debugging, and bloats object files.) C++17 if constexpr supersedes tag dispatch in almost every situation (see note below) and we're using it in new C++17-and-later code. We can use it in C++14 mode too (compilers support it unconditionally with a warning that we've suppressed).

We should finish overhauling the STL to use if constexpr.

Note: Tag dispatch works with delegating constructors, whereas if constexpr works only in function bodies. subrange's delegating constructors are a rare example of necessary tag dispatch:

template <class _Rng>
constexpr subrange(true_type, _Rng&& _Val)
: subrange(_STD forward<_Rng>(_Val), static_cast<_Size_type>(_RANGES size(_Val))) {
// delegation target for subrange(_Rng&&) when we must store the range size
_STL_INTERNAL_STATIC_ASSERT(_Store_size);
}
template <class _Rng>
constexpr subrange(false_type, _Rng&& _Val) : subrange(_RANGES begin(_Val), _RANGES end(_Val)) {
// delegation target for subrange(_Rng&&) when we need not store the range size
_STL_INTERNAL_STATIC_ASSERT(!_Store_size);
}