1

I was practicing vectors and ranges in c++ 20 was stuck at following state.

#include <iostream>
#include <vector>
#include <random>
#include <ranges>
#include <algorithm>

namespace ranges = std::ranges;

struct Model
{
    double next_event_time;
};

std::vector<Model> generate_examples(int number)
{
    // A uniform random number generator object
    // Used as the source of randomness
    std::default_random_engine generator;

    // Calls () operator on generator to get uniformly-distributed integers
    // then transforms the obtained values to output the disired distribution

    // Will uniformly generate values between 0 ~ 1
    std::uniform_real_distribution<double> distribution(0.0, 1.0);

    std::vector<Model> models;

    for (auto i = 0; i < number; i++)
    {
        models.push_back(Model{.next_event_time = distribution(generator)});
    }

    return models;
}

Model get_next_model(const std::vector<Model> &models)
{
    ranges::sort(models | std::views::transform([](const Model &x) { return x.next_event_time; }));

    return models[0];
}

int main()
{
    std::vector<Model> models = generate_examples(10);

    for (const auto &model : models)
        std::cout << model.next_event_time << std::endl;
}

I compiled the code with g++ 10.2 and got error

 error: no match for call to '(const std::ranges::__sort_fn) ~~~
ranges::sort(models | std::views::transform([](const Model &x) { return x.next_event_time; }));

Instead of std::views::transform, I also tried

  1. lambda expression
  2. ranges::sort(models, {}, &Model::next_event_time)

But they all produced similar no match for call to error. Why is this happening?

cpplearner
  • 13,776
  • 2
  • 47
  • 72
Inyoung Kim 김인영
  • 1,434
  • 1
  • 17
  • 38

1 Answers1

2

Your function should be as this:

Model get_next_model( std::vector<Model> models)
{

    ranges::sort(models, ranges::less{}, [](const Model &x) { return x.next_event_time; });

    return models[0];
}

There were two problems:

  1. You cannot sort const object (so remove const&)
  2. The signature of sort requires way of sorting (ranges::less) before projections. And transform has no sense here
PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
  • Why not pass by reference `std::vector &model`? I understand that since something inside has to be modified in order to sort, so I can't use `const`. – Inyoung Kim 김인영 Feb 28 '21 at 00:41
  • yes, exactly. It is the same as expecting that this code will work `int foo(const int& x) { x = 7; return x; }` – PiotrNycz Feb 28 '21 at 00:43
  • I don't understand why you said remove `const&` instead of just `const`. I tried and it works with reference. And its a reference, so less memory consumption. Why do you suggest removing even the `&`? – Inyoung Kim 김인영 Feb 28 '21 at 00:51
  • 1
    ok, you can keep `&`. But with `&` you'll modify input - I assumied you do not not want to do this, because you used `const &` – PiotrNycz Feb 28 '21 at 01:11