Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

STL container function return values

When looking over the member functions of the STL containers, an odd thought occurred to me. Why don't functions like std::vector<T>::push_back(T) not have an (optional) return value (iterator or even a reference to the appended object)? I know std::string functions like insert and erase return iterators, but that's for obvious reasons. I'd think it'd often save a second line of code that often follows these function calls.

I'm sure the designers of C++ have a very good reason, please enlighten me :)

UPDATE: I'm including a real-world code example here where it could reduce code length:

if( m_token != "{" )
{
    m_targets.push_back( unique_ptr<Target>(new Dough(m_token)) );
    return new InnerState( *(m_targets.back()), this );
}

could be reduced to

if( m_token != "{" )
    return new InnerState( *(m_targets.push_back( unique_ptr<Target>(new Dough(m_token)) )), this );

If I assume std::list::push_back returns a reference to the added element. The code is a bit heavy, but that's mostly (two sets of parentheses) due to unique_ptr's constructor and dereferencing it. Perhaps for clarity a version without any pointers:

if( m_token != "{" )
{
    m_targets.push_back( Dough(m_token) );
    return new InnerState( m_targets.back(), this );
}

vs.

if( m_token != "{" )
    return new InnerState( m_targets.push_back( Dough(m_token) ), this );
like image 379
rubenvb Avatar asked Jul 04 '10 19:07

rubenvb


People also ask

Are STL containers passed by reference?

@BjörnPollex Yes! I forgot to mention that.

What are functions in STL?

Functions. The STL includes classes that overload the function call operator. Instances of such classes are called function objects or functors. Functors allow the working of the associated function to be customized with the help of parameters to be passed.

What is containers in STL?

Containers are the objects used to store multiple elements of the same type or different. Depending on that they can be further classified as − Sequence containers (array, vector, list) Associative containers (set, map, multimap)

What is STL containers in C++?

The C++ STL (Standard Template Library) is a powerful set of C++ template classes to provide general-purpose classes and functions with templates that implement many popular and commonly used algorithms and data structures like vectors, lists, queues, and stacks.


1 Answers

Returning the added element, or the container in container member functions is not possible in a safe way. STL containers mostly provide the "strong guarantee". Returning the manipulated element or the container would make it impossible to provide the strong guarantee (it would only provide the "basic guarantee"). The reason behind this is, that returning something could possibly invoke an copy-constructor, which may throw an exception. But the function already exited, so it fulfilled its main task successfully, but still threw an exception, which is a violation of the strong guarantee. You maybe think: "Well then lets return by reference!", while this sounds like a good solution, its not perfectly safe either. Consider following example:

MyClass bar = myvector.push_back(functionReturningMyClass()); // imagine push_back returns MyClass&

Still, if the copy-assignment operator throws, we dont know if push_back succeded or not, thus indirectly violating the strong-guarantee. Even though this is not a direct violation. Of course using MyClass& bar = //... instead would fix this issue, but it would be quite inconvenient, that a container might get into an indeterminate state, just because someone forgot a &.

A quite similar reasoning is behind the fact that std::stack::pop() does not return the popped value. Instead top() returns the topmost value in a safe way. after calling top, even when a copy-constructor, or a copy-assignment constructor throws, you still know that the stack is unchanged.

EDIT: I believe returning an iterator for the newly added element should be perfectly safe, if the copy-constructor of the iterator-type provides the no-throw guarantee (and every i know of does).

like image 75
smerlin Avatar answered Oct 24 '22 04:10

smerlin