0

I've seen this example question on how to use ranges::actions::insert with a vector but I couldn't get it working with a map container.

Would someone show me how to use it in this case, please?

I'm trying, using the ranges actions::insert function to insert all the elements of map m into map r. This is not the final result (and I know there are other cleaner methods to do a copy but these aren't relevant to my current needs) but shows me in the meantime how to use the actions::insert function. Final result will look something like:

auto v = m | ranges::views::for_each(return <something conditional true>) | ranges::actions::insert(r, r.end(), <all the element data of m>);

The code I'm using is here:

#include "https://raw.githubusercontent.com/HowardHinnant/date/master/include/date/date.h"
#include <chrono>
#include <fmt/format.h>
#include <iostream>
#include <limits>
#include <map>
#include <range/v3/all.hpp>

struct pivot_t {
  double price;
  double s;
  unsigned int d;
  std::chrono::system_clock::time_point timestamp;

  pivot_t() : price(0.0), s(0.0), d(0){};
  pivot_t(const double price, const double s, const unsigned int d,
          const std::chrono::system_clock::time_point timestamp)
      : price(price), s(s), d(d), timestamp(timestamp){};
};

auto main() -> int {
  using namespace date;
  using namespace std::chrono;
  using namespace std::chrono_literals;

  // Just used as a reference time point
  const auto tp_now = std::chrono::system_clock::from_time_t(0);

  const auto m = std::map<system_clock::time_point, pivot_t>{
      {tp_now + 0min, {1.1, 1.11, 0, tp_now + 0min}},
      {tp_now + 1min, {2.2, 2.22, 0, tp_now + 1min}},
      {tp_now + 2min, {3.3, 3.33, 0, tp_now + 3min}},
      {tp_now + 3min, {4.4, 4.44, 0, tp_now + 3min}},
      {tp_now + 4min, {3.3, 3.33, 0, tp_now + 4min}},
      {tp_now + 5min, {4.4, 4.44, 0, tp_now + 5min}},
      {tp_now + 6min, {7.7, 7.77, 0, tp_now + 6min}},
      {tp_now + 7min, {8.8, 8.88, 0, tp_now + 7min}},
      {tp_now + 8min, {9.9, 9.99, 0, tp_now + 8min}},
      {tp_now + 9min, {10.10, 10.1010, 0, tp_now + 9min}},
      {tp_now + 10min, {11.11, 11.1111, 0, tp_now + 10min}},
      {tp_now + 11min, {12.12, 12.1212, 0, tp_now + 11min}},
      {tp_now + 12min, {13.13, 13.1313, 0, tp_now + 12min}},
      {tp_now + 13min, {14.14, 14.1414, 0, tp_now + 13min}}};

    auto r = std::map<system_clock::time_point, pivot_t>{};

    auto push_r = [](auto& elem) { return {elem.first, {elem.second.price, elem.second.s, elem.second.d, elem.first}}; };

    // This line effectively makes a copy of m into v. 
    // This is not the final required opertation but it does prove the insert syntax.
    auto v = m | ranges::actions::insert(r, r.end(), push_r);

    for(auto& i : v)
        std::cout << i.first << " = " << i.second.price << std::endl;

    return 0;
}

live demo

I'm using a lambda as it's the only way I could think of to reference the individual m elements for insertion into the r map. If there's another (better?) way of doing this then please share.

The error I'm receiving is this:

error: no match for call to '(const ranges::adl_insert_detail::insert_fn) (std::map<std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long int, std::ratio<1, 1000000000> > >, pivot_t>&, std::map<std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long int, std::ratio<1, 1000000000> > >, pivot_t>::iterator, main()::<lambda(auto:28&)>&)'

I presume this is telling me my syntax is incorrect but I don't know how to solve it.

My objective is to use the insert function in the following fashion:

auto v = m | ranges::views::for_each(<selective lambda tbd>) | ranges::actions::insert(r, r.end(), <copy the m (pivot_t complex type) elements to map r (pivot_t complex type) - use a lambda here or other method>)
cigien
  • 57,834
  • 11
  • 73
  • 112
Andrew
  • 626
  • 6
  • 16
  • 1
    What're you actually trying to do? – Barry Sep 10 '21 at 21:38
  • I'm trying, using ranges the `actions::insert` function to insert all the elements of map m into map r. This is not the final result (and I know there are other cleaner methods to do a copy but these aren't relevant to my current needs) but shows me in the meantime how to use the `actions::insert` function. Final result will look something like: `auto v = m | ranges::views::for_each(return ) | ranges::actions::insert(r, r.end(), );` if this makes sense. – Andrew Sep 10 '21 at 21:59
  • Please add all relevant information to the question itself, instead of as a comment. Also, it would be helpful if you showed what the resulting map is supposed to be. – cigien Sep 10 '21 at 22:04

1 Answers1

1

There are several things wrong here.

// This line effectively makes a copy of m into v. 
// This is not the final required opertation but it does prove the insert syntax.
auto v = m | ranges::actions::insert(r, r.end(), push_r);
  1. You cannot pipe into ranges::actions::insert.
  2. ranges::actions::insert returns the result of insert, which for a map is a pair<iterator, bool> (and not a range of some kind that you can iterate over, so v is not useful to you)
  3. None of the arguments into insert is a callable. You either provide a value, a range, an initializer_list, an iterator/sentinel pair, or a position into the source range and one of those other things.
  4. The lambda push_r is itself invalid - it's just doing return { ... } without anywhere that specifies the type. You can't just return a braced-init-list like that, you need a type somewhere (either return T{...}; or a trailing-return-type like -> T

I'm trying, using the ranges actions::insert function to insert all the elements of map m into map r

That's:

ranges::actions::insert(r, m);
Barry
  • 286,269
  • 29
  • 621
  • 977
  • Thanks for clarifying these points, I wasn't aware of any of them. Now, considering my stated objectives of "selectively" inserting `m` records into the `r` map, how should I achieve this using ranges? Is it possible? – Andrew Sep 10 '21 at 22:22
  • @Andrew I don't know where those are your "stated objectives", but you just insert whatever range you want. If what you want is a filtered version of m, that's `insert(r, m | filter(predicate))` – Barry Sep 10 '21 at 22:24