Hichigaya Hachiman
Hichigaya Hachiman

Reputation: 307

Last element of a list in a loop

I have a list<Thing*> clothes. I want to print out things to a desired format:

+- shirt
+- pants
\\ shoes

So basically the output is the same for all but the last iteration. So far I've attempted this:

string CCloset::OutputContent() const {
    string output;
    for(auto i : this->clothes) {
        if( next(i) == this->clothes.end() ) {
            output.append("\\");
        } else {
            output.append("+-");
        }

        output.append( i->Output() );
    }
    return output;
}

The theory is that if next iteration causes iterator i to be at list.end() it means we're at the last element so we slightly modify the output. The compiler says Can't compare structures.

next() returns iterator pointing to the next element. In the case of last element, it would point to past-the-end of list. list.end() returns iterator pointing to past-the-end of list.

What am I missing?

Upvotes: 0

Views: 933

Answers (2)

Rakete1111
Rakete1111

Reputation: 48938

i is not an iterator. std::next can only be called with a ForwardIterator or an InputIterator, not with an element of a container.

This is one of the only use-cases for iterator based loops:

for(auto it = clothes.begin(); it != clothes.end(); ++it) {
    if( it + 1 == clothes.end() ) {
        output.append("\\");
    } else {
        output.append("+-");
    }

    output.append( (*it)->Output() );
}

Upvotes: 1

zett42
zett42

Reputation: 27756

As commenters already noted, i is not an iterator, but the value of the element.

If you modify the loop to use a reference instead of a value, you can compare the address of the current element with the address of the last element like this:

for( const auto& i : this->clothes ) {
    if( &i == &this->clothes.back() ) {
        output.append("\\");
    } else {
        output.append("+-");
    }

    output.append( i->Output() );
}

Live demo on Coliru.

Upvotes: 3

Related Questions