1

I have a container which is actually a std::shared_ptr< std::vector< Element > >. I wrapped this type into a MyVector class because I do not want people to mess the things up with the pointer:

class MyVector
{
    std::shared_ptr< std::vector< Element > > m_vector;
};

I want to be able to use MyVector into a range-based for loop like this:

int main( )
{
    MyVector vector;

    // ...

    for( const auto& element : vector )
    { 
        // ...
    }

    return 0;
}

So now I have to redirect to the internal pointer the correct functions in order to make it work. To which C++ Concept must MyVector be compliant? And how can I achieve the result that when the internal std::shared_ptr is nullptr, MyVector behaves exactly like an empty std::vector (so that it will not crash on a range-based loop, but will just make no iteration at all)?

nyarlathotep108
  • 5,275
  • 2
  • 26
  • 64

1 Answers1

-2

To answer your question take a look at the explanation of range based for loops as in the cppreference documentation

{
    auto && __range = range_expression ; 
    auto __begin = begin_expr ;
    auto __end = end_expr ;
    for ( ; __begin != __end; ++__begin) { 
        range_declaration = *__begin; 
        loop_statement 
    } 
} 

And this quote

If range_expression is an expression of a class type C that has a member named begin and/or a member named end (regardless of the type or accessibility of such member), then begin_expr is __range.begin() and end_expr is __range.end();

  1. So firstly you need to provide a begin() method, an end() method. Both should return an instance of some sort of iterator class (they can be of different types!)

  2. The iterator returned by begin() should support the preincrement operator and the dereference operator as inferred from the explanation above.

  3. And finally the iterators returned by begin() and end() should be comparable with a !=.

Curious
  • 20,870
  • 8
  • 61
  • 146
  • @Curious and how can I achieve the effect that when the internal pointer is `nullptr`, the container behaves like an empty `std::vector` (for the range-loop purpose)? I can easily forward `begin()` and `end()` when the pointer is available, but I have no clue when the pointer is not there. – nyarlathotep108 Jul 07 '17 at 10:00
  • 1
    @nyarlathotep108 make `end()` return an iterator which is initialized with `nullptr` and in the case where your container is empty have `begin()` do the same. And then in the comparison operator compare whether the two have the same pointer, if so they compare equal – Curious Jul 07 '17 at 10:02
  • @nyarlathotep108: Have a static empty vector private to the class. If the pointer is null, then begin and end can return the begin/end of this static. – Martin Bonner supports Monica Jul 07 '17 at 10:03