a more explicit type instead of auto for std::ranges::views result [duplicate]
Asked Answered
S

1

0

auto is really nice to maintain a single definition and avoid some typing. It's also necessary for std::ranges::views. However, auto can make code harder to read it's too far from the defining type (particularly in code review). Replacing it with an explicit type can also validate that the type is what you expect (e.g. before passing it to a templated function and winding up in a world of template error message hurt). There needs to be a balance. Unfortunately, auto is necessary for views (I assume since the type is implementation dependent).

#include <ranges>

// Provided in some other header
template<class Range>
auto process(Range&& range)
{
    return range | std::ranges::views::transform(&Foo::i);
}

// main.cpp
struct Foo { int i; };

void func()
{
    Foo foos[4];

    // What is result and what can you do with it?
    auto result = process(foos);
}

Is there something I can replace auto with that makes the type a bit more clear?

Serviceman answered 15/5 at 1:39 Comment(3)
What's wrong with auto? In the end it is a "how" not a "what", and usually something like intellisense can quickly show what the types is (just hover over result).Cipher
@PepijnKramer in the example above, I would need to look at the definition of process() to guess at what result is - is it a primitive type, a container, who knows. Even then it may be a few definitions deep. Hovering over result in an editor doesn't help with complicated definitions such as those returned by std::ranges::views. You're exactly right though - I want to know what I can do with result and I don't mind so much about the exact type.Serviceman
If the CPO in views has a counterpart class suffixed with _view in ranges you can use that, and operand to return becomes a bunch of nested braced initializers. But some CPOs don't correspond to a single class template, and you'd have to work your way.Anthracene
S
2

auto can be constrained with C++ concepts

template<typename Range, typename T>
concept range_of = std::same_as<std::ranges::range_value_t<Range>, T>;

...

range_of<int> auto result = process(foos);

// range_of<float> auto result = process(foos); // error. thanks, compiler!

I'm not aware of anything like range_of in the standard library, but it'd be nice if there were.

Serviceman answered 15/5 at 1:39 Comment(1)
There is std::ranges::view concept, if you look at return type of standard library views functions, for example std::views::take they return std::ranges::view auto. While it doesn't specify the elements of the view, it is still makes the type a bit more clear, as was asked in the question. So one can do in their code: std::vector vec1{1,2,3,4}; std::ranges::view auto view1 = std::views::take(vec1, 2);Pose

© 2022 - 2024 — McMap. All rights reserved.