Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I often use the following syntax:

std::vector<foo> vec;
vec.push_back( someClass.getFoo(...).modifyAndReturn() );

Considered about exception safety, I quote the standard on vector's push back behavior (23.3.7.5):

If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move assignment operator of T or by any InputIterator operation there are no effects. If an exception is thrown by the move constructor of a non-CopyInsertable T, the effects are unspecified.

  • Is it a good practice to use complicated push backs?
  • Are there any perils exception wise?
share|improve this question

migrated from codereview.stackexchange.com Feb 19 at 8:20

This question came from our site for peer programmer code reviews.

    
Not exception wise, but normally, it is not a good practice to use call chains like that. When the API was designed specially for this it's fine (i.e. it is OK for std::cout to have a chain of << calls, but not for someClass). If you have many someClass.getFoo(...).xyz constructs, consider refactoring those into a method of someClass. That means, the code should be: vec.push_back( someClass.modifiedFooValue() );. –  utnapistim Feb 19 at 14:37
add comment

2 Answers

Whether using such complicated expressions in a push back (or any other function call) is debatable and it depends on two factors: 1. your local coding conventions, and 2. the comfort level of you and your team with reading such expressions

Regarding exception safety, there is no difference between these three snippets:

std::vector<foo> vec;
vec.push_back( someClass.getFoo(...).modifyAndReturn(...) );

std::vector<foo> vec;
auto temp = someClass.getFoo(...).modifyAndReturn(...);
vec.push_back( temp );

std::vector<foo> vec;
auto temp = someClass.getFoo(...);
auto temp2 = temp.modifyAndReturn(...);
vec.push_back( temp2 );

The exception safety of std::vector<>::push_back does not really enter into the picture, because if getFoo or modifyAndReturn would throw an exception, push_back won't even be called. In C++, arguments to a function are always evaluated before the function gets called.

share|improve this answer
add comment

The push back is not complicated. Its argument is (somewhat).

If this is a common idiom and consistently used through the code, then it's good practice. I might prefer to evaluate the argument into a helpfully-named local variable to assist readers in understanding the meaning of the value, but then again, I might not. If I knew Class and Foo, I would understand this code.

The perils referred to in this excerpt are related to exceptions that might be raised inside vector as a result of invoking various kinds of constructor or copying operation. Exceptions raised during evaluation of the argument are external to vector, and would be the same if you evaluated the argument separately. Likewise, exceptions raised internal to vector would not be avoided by prior evaluation of the arguments. I see nothing to fear.

Go for it. You're doing fine.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.