0

I'm making a calculator that can accept more than one operator at once (e.g. 5x5x5). I have a map that contains the positions of the operators, and what type they are (x/+-). I also have a for loop for (auto const& [key, val] : oper_map) which I got from this post.

In order to get the left and right numbers, I need to know where the left and right operators are. I've attempted to use std::prev and std::next with the key like this:

int loper_pos = -1;
int roper_pos = 0;
double lnum;
double rnum;
char loper;
char roper;

//map defined elsewhere
for (auto const& [key, val] : oper_map)
{
    //loper is left operator while roper is right opeprator

    //tracks the position of the loop
    int map_pos = std::distance(oper_map.begin(), oper_map.find(key)); 

    if (map_pos == 0) loper_pos = -1;
    else
    {
        loper_pos = std::prev(key);
        loper = std::prev(val);
    }
    if (map_pos == oper_map.size()) roper_pos = oper_map.size() + 1;
    else
    {
        roper_pos = std::next(key);
        roper = std::next(val);
    }

but I guess it doesn't work since key isn't an iterator? I also can't increment/decrement key or val (or when using the C++11 version in this post), so I guess it doesn't count as an iterator? I don't know iterators confuse me.

This post appears to be what I want but for whatever reason lower_bound() does not work with oper_map; no suitable conversion.

Marek R
  • 27,988
  • 5
  • 42
  • 123
Shidouuu
  • 169
  • 2
  • 11
  • Just change your loop to use an iterator... ? – super Mar 10 '21 at 14:55
  • when you care about the position don't use a range based loop. The purpose of the range based loop is to hide iterators behind an abstraction, but you want iterators – 463035818_is_not_a_number Mar 10 '21 at 14:56
  • I think a `std::vector>` would be more suitable. (Actually, there is most likely some even more suitable structure, like a syntax tree.) – molbdnilo Mar 10 '21 at 14:57
  • @molbdnilo Huh, well I read somewhere you shouldn't use pairs in a vector when you could use a map, would those values be easier to access? – Shidouuu Mar 10 '21 at 14:59
  • " you shouldn't use pairs in a vector when you could use a map" in this generality the statement is just wrong – 463035818_is_not_a_number Mar 10 '21 at 15:00
  • 1
    @Shidouuu The word "could" is sneaky. In this context, it pretty much means "if you mostly look up specific keys" - that is, if you treat your vector as a map - not "if it is possible". If you're mostly interested in the sequence of values, e.g. finding the previous or next one, a map is less efficient in both time and space (and simplicity). – molbdnilo Mar 10 '21 at 15:14

1 Answers1

1

No. key is not an iterator.

for (auto const& [key, val] : oper_map)

key is a const reference to the key in the map. If you want iterators, use iterators:

for (auto it = oper_map.begin(); it != oper_map.end(); ++it) {
    auto next = std::next(it);
    auto prev = std::prev(it);
}

However, consider that std::map is not a sequential container. If you are interested in the positions of elements in the container, maybe a std::vector< std::pair<Key,MappedValue>> is more handy (note that complexity of std::next is linear for bidirectional iterators (map) while it is constant for random access iterators (vector), same is true for std::prev).

463035818_is_not_a_number
  • 88,680
  • 9
  • 76
  • 150