Home > Blockchain >  for loop does not compile with vanilla operations with MSVC
for loop does not compile with vanilla operations with MSVC

Time:09-17

I've had trouble compiling iterator logic in MSVC. It results in a compilation error when trying to express an iteration using the short-hand for (type element: container) { ... }

It could be duplicate but I am unaware what keywords to search for..

Using MSVC 2019, C 17 compilation mode

/// iterator
template <typename T>
struct iter2 {
    T      *start;
    size_t  index;
    ///
    void operator  () { index  ; }
    void operator--() { index--; }
    ///
    operator    T& () const { return  start[index]; }
    ///
    bool operator==(iter2 b) const { return start == b.start && index == b.index; }
    bool operator!=(iter2 b) const { return start != b.start || index != b.index; }
    /// defined ctr
    iter2(T *start, size_t index) : start(start), index(index) { }
};

// a trivial structure.
struct field2 { int key, val; };

///
template <typename T>
struct array2 {
    /// just a simple C   array
    T     buffer[100];
    int   count;
    iter2<T> begin() { return iter2<T>(buffer, 0);     };
    iter2<T>   end() { return iter2<T>(buffer, count); };
};

static bool exists(int k) {
    /// populate an array with some copied data
    field2      f1 = {}, f2 = {};
    array2<field2> a;
    a.buffer[0] = f1;
    a.buffer[1] = f2;
    a.count     = 2;

    /// iterate through as the shorthand for (type element:container) iterate 'should' ?
    /// compiles on msvc 2019, c   17
    for (iter2<field2> it = a.begin(), e = a.end(); it != e;   it) {
        field2 &f = (field2 &)it;
        if (f.key == k)
            return true;
    }

    /// does not compile, and says:
    /// (...,26): error C2100: illegal indirection
    for (field2 &f: a) {
        if (f.key == k)
            return true;
    }

    return null;
}

int main(int argc, char **argv) {
    exists(0);
    return 0;
}

CodePudding user response:

Your iter2 type does not satisfy the requirements of an input iterator, as it does not implement operator*, which a range-for loop uses to access the elements that are being iterated.

You need to add this to iter2:

T& operator*() { return start[index]; }

And then consider removing operator T&(), as that is not an operator that an iterator should or need to implement.

And then, in exists(), you can change your non-range for loop to use field2 &f = *it; instead.


On a side note, your pre-increment/decrement operators should return a reference to the iterator that is being updated, eg:

iter2& operator  () {   index; return *this; }
iter2& operator--() { --index; return *this; }

And, consider adding post-increment/decrement operators, too:

iter2 operator  (int) { iter2 temp(*this);   index; return temp; }
iter2 operator--(int) { ite2 temp(*this); --index; return temp; }

You might also consider adding an operator->, too:

T* operator->() { return &start[index]; }
  • Related