How do I declare a template parameter of type Range?

Viewed 173

I am not sure if it is a correct code, but at least as an example, I was able to declare a template parameter of type rage as follows:

template <std::ranges::range Range>
inline auto TransformIt(Range r)
{
    return r | std::views::transform([](int n) { return n * n; });
}

int main()
{
    std::vector<int> v;
    auto r = TransformIt(v);
    return 0;
}

but I was unable to improve my code like this:

template <std::ranges::range<int> Range>
inline auto TransformIt(Range r)
{
    return r | std::views::transform([](int n) { return n * n; });
}

what is the right syntax for that?

1 Answers

std::ranges::range<int> doesn't do what you think it does. This is the concept range applied over int, i.e. you check weather int is a range ... which it isn't.

One way of achieving what you need is:

template <std::ranges::range Range>
    requires std::same_as<std::ranges::range_value_t<Range>, int>
auto TransformIt(Range r)
{
    return r | std::views::transform([](int n) { return n * n; });
}

If you want you can create a new concept:

template <class R, class Value>
concept range_over = std::ranges::range<R> && 
    std::same_as<std::ranges::range_value_t<R>, Value>;

template <range_over<int> Range>
auto TransformIt(Range r)
{
    return r | std::views::transform([](int n) { return n * n; });
}

Depending on your needs you might want to change same_as with convertible_to.

Side note: as TransformIt is a template function inline keyword is redundant and idiomatically not used.

Related