modernize-use-emplace¶
The check flags insertions to an STL-style container done by calling the
push_back method with an explicitly-constructed temporary of the container
element type. In this case, the corresponding emplace_back method
results in less verbose and potentially more efficient code.
Right now the check doesn’t support push_front and insert.
It also doesn’t support insert functions for associative containers
because replacing insert with emplace may result in
speed regression, but it might get support with some addition flag in the future.
By default only std::vector, std::deque, std::list are considered.
This list can be modified using the ContainersWithPushBack option.
Before:
std::vector<MyClass> v;
v.push_back(MyClass(21, 37));
std::vector<std::pair<int, int>> w;
w.push_back(std::pair<int, int>(21, 37));
w.push_back(std::make_pair(21L, 37L));
After:
std::vector<MyClass> v;
v.emplace_back(21, 37);
std::vector<std::pair<int, int>> w;
w.emplace_back(21, 37);
w.emplace_back(21L, 37L);
By default, the check is able to remove unnecessary std::make_pair and
std::make_tuple calls from push_back calls on containers of
std::pair and std::tuple. Custom tuple-like types can be modified by
the TupleTypes option; custom make functions can be modified by the
TupleMakeFunctions option.
The other situation is when we pass arguments that will be converted to a type inside a container.
Before:
std::vector<boost::optional<std::string> > v;
v.push_back("abc");
After:
std::vector<boost::optional<std::string> > v;
v.emplace_back("abc");
In some cases the transformation would be valid, but the code wouldn’t be
exception safe. In this case the calls of push_back won’t be replaced.
std::vector<std::unique_ptr<int>> v;
v.push_back(std::unique_ptr<int>(new int(0)));
auto *ptr = new int(1);
v.push_back(std::unique_ptr<int>(ptr));
This is because replacing it with emplace_back could cause a leak of this
pointer if emplace_back would throw exception before emplacement (e.g. not
enough memory to add a new element).
For more info read item 42 - “Consider emplacement instead of insertion.” of Scott Meyers “Effective Modern C++”.
The default smart pointers that are considered are std::unique_ptr,
std::shared_ptr, std::auto_ptr. To specify other smart pointers or
other classes use the SmartPointers option.
Check also doesn’t fire if any argument of the constructor call would be:
- a bit-field (bit-fields can’t bind to rvalue/universal reference)
- a
newexpression (to avoid leak)- if the argument would be converted via derived-to-base cast.
This check requires C++11 or higher to run.
Options¶
-
ContainersWithPushBack¶ Semicolon-separated list of class names of custom containers that support
push_back.
-
IgnoreImplicitConstructors¶ When non-zero, the check will ignore implicitly constructed arguments of
push_back, e.g.std::vector<std::string> v; v.push_back("a"); // Ignored when IgnoreImplicitConstructors is ``1``.
Default is
0.
-
SmartPointers¶ Semicolon-separated list of class names of custom smart pointers.
-
TupleTypes¶ Semicolon-separated list of
std::tuple-like class names.
-
TupleMakeFunctions¶ Semicolon-separated list of
std::make_tuple-like function names. Those function calls will be removed frompush_backcalls and turned intoemplace_back.
Example¶
std::vector<MyTuple<int, bool, char>> x;
x.push_back(MakeMyTuple(1, false, 'x'));
transforms to:
std::vector<MyTuple<int, bool, char>> x;
x.emplace_back(1, false, 'x');
when TupleTypes is set to MyTuple and TupleMakeFunctions
is set to MakeMyTuple.