Search code examples
c++c++20argument-dependent-lookupstd-ranges

Why do `std::ranges::size` require a non-const method when using ADL?


Otherwise, size(t) converted to its decayed type, if ranges::disable_sized_range<std::remove_cv_t<T>> is false, and the converted expression is valid and has an integer-like type, where the overload resolution is performed with the following candidates:

  • void size(auto&) = delete;
  • void size(const auto&) = delete; 1
class Test {
    friend size_t size(/*const*/ Test&) {
        return 0;
    }
};

int main() {
    std::ranges::size(Test{});
    // no matching function error when adding the `const` qualifier
}

https://godbolt.org/z/79e5vrKrT


Generally, size method doesn't require to modify the range, like what std::size does.

Why is there such a constraint of std::ranges::size? (Seems it's only performed for non-member version.)


Solution

  • Why is there such a constraint of std::ranges::size? (Seems it's only performed for non-member version.)

    Although the size method does not modify the range, some ranges do not have a const-qualified member begin(), which allows only non-const-qualified objects to model a range.

    This also makes some range adaptors in the standard may only have a non-const-qualified size.

    For your example, considering that Test only has non-const begin/end or size, then friend size_t size(Test&) can really only be the option.