S.H
S.H

Reputation: 955

C++11 range-based for-loop: how to use a container with objects and pointers-to-object

I have two containers:

std::vector< ObjectClass  > vecD; // container of objects
std::vector< ObjectClass* > vecP; // container of pointers

in my code, I want to loop over all elements. As far as I know, I need to write distinct for loops, that means

// container of objects
for ( const auto& elem : vecD )
    elem.doStuff();


// container of pointers
for ( const auto& elem : vecP )
    elem->doStuff();            // the "->" is needed instead of "."

Is there a way to tell the loop "if the elemets are objects, use them directly. Otherwise, dereference them first"?

update Here is a more elaborate example to clarify:

I have those containers. These are each used in a templated function:

template< typename ContainerT >
void myfunc( const ContainerT& container)
{
    for ( const auto& elem : container )
    {
        if ( elem_is_a_pointer ) //how can this work?
            elem->doStuff();     //  member function
        else
            elem.doStuff();
    }
}

Upvotes: 0

Views: 95

Answers (3)

TartanLlama
TartanLlama

Reputation: 65770

You could write a non-member function to do the dispatch:

void doStuff (const ObjectClass& obj) {
    obj.doStuff();
}

void doStuff (const ObjectClass* obj) {
    obj->doStuff();
}

Then you can write both loops in the same way:

for ( const auto& elem : vecD )
  doStuff(elem);

for ( const auto& elem : vecP )
  doStuff(elem);

For the code in your edit, you could write a simple helper function to strip off pointers, then call on that:

template <typename T>
T& strip_pointers (T& obj) {
    return obj;
}
template <typename T>
T& strip_pointers (T* obj) {
    return *obj;
}

template< typename ContainerT >
void myfunc( const ContainerT& container)
{
    for ( const auto& elem : container )
    {
        strip_pointers(elem).doStuff();
    }
}

Upvotes: 1

nh_
nh_

Reputation: 2241

You could write little helpers, which perform the dereferencing if neccessary

template<typename T>
T& deref(T* p) { return *p; }
template<typename T>
T& deref(T& p) { return p; }

then the code for the loops is equivalent

// container of objects
for ( const auto& elem : vecD )
    deref(elem).doStuff();

// container of pointers
for ( const auto& elem : vecP )
    deref(elem).doStuff();  

Upvotes: 2

ISanych
ISanych

Reputation: 22710

Nope, but you could use next approach:

for ( const auto* pElem : vecP )
{
    const auto& elem = *pElem;
    elem.doStuff();
}

Upvotes: 0

Related Questions