Search code examples
c++std-rangesc++23

Why is iter_const_reference_t not simply using std::add_const_t?


iterator_const_reference_t is implemented as follows:

template<std::indirectly_readable T>
using iter_const_reference_t = std::common_reference_t<const std::iter_value_t<T> &&,
                                                       std::iter_reference_t<T>>;

But why? Why isn't it simply: std::add_const_t<std::iter_reference_t<T>>?


Solution

  • add_const_t<int&> will still be int&, which is not a const reference. You probably mean const iter_value_t<T>& but that might lead to dangling issues.

    The formula in your question comes from range/v3 which has been around for years and can handle almost all cases including proxy references.

    For example, the reference of zip_view's iterator, namely tuple<int&, int&>, cannot be made a const reference just by adding a top-level const-qualifier.

    In this case, we can apply common_reference's specialization for tuple to produce the correct reference type i.e. tuple<const int&, const int&>, that's why the formula of iter_const_reference_t has the common_reference part.