-2
#include <iostream>
#include <vector>
#include <string>
#include <variant>

struct S1 { int a {}; };
struct S2 { std::string b {}; };
using Struct_variant = std::variant< S1, S2 >;

int main() {
    std::vector<Struct_variant> struct_vector { S1 {1}, S2 {"hello"}, S1 {3}};
    size_t index_to_erase {1};  // NOTE: assume we only know the index, *not* the iterator.
    auto variant_itr = struct_vector.begin();

    // following line requires either a std::vist, or an "if std::holds_alternative" to handle types.
    variant_itr =  struct_vector.begin() * index_to_erase;
    // for (int i = 0; i != index_to_erase; i++) variant_itr++;  // works
    struct_vector.erase(variant_itr);
    std::cout << struct_vector.size() << std::endl;
}

I don't fully understand why increment works, where multiply does not. What is the static_cast<>()?

Any assistance is appreciated.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Grant Rostig
  • 473
  • 1
  • 4
  • 13

2 Answers2

3

Multiplying an iterator or pointer has no definition or meaning. A "point in space" cannot be "multiplied", either in programming nor in real life. Only distances/spans/quantities can be multiplied.

It looks like you simply wish to advance the iterator by index_to_erase spaces. That's addition.

const auto variant_itr = struct_vector.begin() + index_to_erase;

That's it!

The logic to turn this into some underlying pointer advance of index_to_erase*sizeof(Struct_variant) is done for you, if indeed the iterator for your container is as simple as a pointer into the data.

Note that this only works for random-access iterators; more generally you can use std::advance or std::next, but if you find yourself needing that then your solution is probably not efficient.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Just to be sure, the inefficient solution you are referring to is if the container is not a random-access iterator, is that correct? Additionally, using std::advance should be just as fast as "+ index_to_erase" for a vector, correct? – Grant Rostig Jan 12 '20 at 21:26
  • 1
    @GrantRostig Exactly – Lightness Races in Orbit Jan 13 '20 at 10:31
  • 1
    @GrantRostig For example, a `std::list` _won't let you_ just do `+` because it knows this is not a cheap operation, but you can still do `std::advance`/`std::next` if you're desperate - you can see how such a usage would then be potentially suspicious :P – Lightness Races in Orbit Jan 13 '20 at 10:31
1

I don't fully understand why increment works, where multiply does not.

Short answer: over iterators, the increment (++) operator is defined, multiplications isn't.

Long answer

Operation over iterator aren't algebra where begin() position has the 1 value.

An iterator is the evolution of a pointer, that is a number that represent a position in memory, and in first approximation (an also second approximation, with std::vectors) you can reason thinking an iterator as a pointer .

Suppose that begin() return 1000 and that the Struct_variant size is 10 (completed invented numbers).

With variant_itr++ you increment the pointer (iterator) value, that is (pointer arithmetic) you doesn't get 1001 (1000 plus 1) but 1010, that is the position for a following Struct_variant.

If you apply increment 5 times (by example), you get a pointer in position 1050, not 1005.

Given this type of arithmetic, is completely without meaning a multiplication.

And is undefined.

max66
  • 65,235
  • 10
  • 71
  • 111
  • Neither iterators nor pointers are "numbers". In fact, thinking of them this way is likely what led the OP to their misunderstanding – Lightness Races in Orbit Jan 12 '20 at 20:03
  • @LightnessRacesBY-SA3.0 - Well... for iterators I understand, I think (we know what we can do with an iterator, but we don't know (and we don't need to know) what an iterator is). But what do you mean saying that pointers aren't "numbers"? Aren't they values representing memory locations? Do you mean that that values aren't "numbers" because there is a completely different arithmetic over them? – max66 Jan 12 '20 at 20:27
  • @max66: Iterators are iterators. Pointers are pointers (which are a kind of iterator). Numbers are numbers. (It is true that pointers look like numbers on real, physical computers, "under the hood", but so does literally everything else, including this website, your movies, your music... This doesn't mean they are conceptually numbers or that they should/can be treated like numbers. Those people who'll say "wow, how pedantic, it doesn't matter" should review the reason that this OP came here with this question. It absolutely matters if you wish to be able to correctly reason about code.) – Lightness Races in Orbit Jan 12 '20 at 20:34
  • @GrantRostig _"I suspect that one can multiply them, with the right cast"_ To what end? What sort of result do you expect? You still haven't explained what you think such an operation would mean/entail. A pointer value is not a span or distance or size - it is an address. A point in "space". You cannot multiply points, either in programming on in reality. Tell us what you're actually trying to do. – Lightness Races in Orbit Jan 12 '20 at 20:37
  • Thanks for your reply, but prior to asking this question, I understood that iterators are not numbers. I was looking at iterators as a special type of pointer. I'm quite certain that one can do arithmetic with pointers, and I suspect that one can add an offset (index*sizeof()) with the right cast. If my presumptions are correct, his question is about accessing the types of variants and iterators. I will fix the question to remove the multiplication of iterators. Thanks for the correction. – Grant Rostig Jan 12 '20 at 20:40
  • @LightnessRacesBY-SA3.0 - I see... well... I'm a "all is numbers" guy and (the worst part) I'm a old C programmer. So for me is difficult think a pointer without thinking it as a number. If I understand correctly, your definition of "number" is a pure value, without a particular meaning. Where pointers are object with a meaning and a number representation. And the meaning make so that increment make sense (but with a different function) and multiplications doesn't make sense. – max66 Jan 12 '20 at 21:34
  • @max66 Pretty much! Sounds like you've got it after all ;) – Lightness Races in Orbit Jan 13 '20 at 10:30
  • @LightnessRacesBY-SA3.0 - Yes, I suppose. This sort of question/problems are, in large part, definition/terminology problems. And I have the additional disability that I think in another language and I don't know English very well. – max66 Jan 13 '20 at 20:32
  • @max66: That can be a problem yes. FWIW your English is excellent. – Lightness Races in Orbit Jan 13 '20 at 20:40