vendredi 26 août 2016

Range-based loop from a temporary returned by a member function

I'm a little unsure how the new (as of c++11) ranged-based loop works internally.

If I were to do something like...

for( auto i : someclass.Elements() )
{
 ...
}

...where "ContentsInReverse" returns a a temporary, are there any side effects I might not be aware of?

I will add a working prototype at the bottom of this question.

I've verified that the type returned by "Elements()" is created once, which is my biggest concern. To be honest, this feels a bit too easy, and I haven't seen this implementation else where.

For context, I have an XML library I created and want to be able to iterate over an element's children ("for( auto child: element->Children() ) {...}"), it's attributes ("for( auto attribute : element->Attributes() ( {...}"), and perhaps more specific children ("for( auto cats : element->Children( "cats" ) ) {...}".

Here is a working prototype:

#include <iostream>
#include <list>
#include <vector>
#include <string>

template< typename T >
class Array
{
public:
    Array()
    {       
    }

    Array( T firstValue )
    {
        m_elements.push_back( firstValue );
    }

    Array( const std::list< T > & values )
    {
        m_elements.insert( m_elements.begin(), values.begin(), values.end() );
    }   

    virtual ~Array() 
    {
    }

    void Add( T value )
    {
        m_elements.push_back( value );
    }

    const T & operator[]( int index ) const
    {
        return m_elements[ index ];
    }   

    size_t Count() const
    {
        return m_elements.size();
    }

    class ElementsIterable
    {
        Array & m_array;
    public:
        ElementsIterable( Array & array ) : m_array( array )
        {
            std::cout << "ElementsIterable Constructed" << std::endl;
        }

        class iterator
        {
        public:
            iterator( Array & array, size_t index )
                : m_array( array ), m_index( index )
            {
            }

            iterator & operator++()
            {
                m_index++;
                return *this;
            }

            bool operator!=( const iterator & itr ) const
            {
                return m_index != itr.m_index;
            }

            const T & operator*() const
            {
                return m_array[ m_index ];
            }

        private:
            Array & m_array;
            size_t m_index;
        };

        iterator begin() {
            return iterator( m_array, 0 );
        }
        iterator end() {
            return iterator( m_array, m_array.Count() );
        }
    };

    ElementsIterable Elements()
    {
        return ElementsIterable( *this );
    }

private:
    std::vector< T > m_elements;
};

int main( int argc, char ** argv )
{
    Array< int > array( { 1, 2, 3 } );
    array.Add( 4 );

    for( auto a : array.Elements() )
    {
        std::cout << a << std::endl;
    }

    return 0;
} 

Aucun commentaire:

Enregistrer un commentaire