简体   繁体   中英

In C++ how does one multiply an iterator of a vector which contains std::variant elements? Doing a cast of the iterator type?

#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.

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.

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::vector s) 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM