1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
.. title:: clang-tidy - modernize-use-emplace
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 <http://htmlpreview.github.io/?https://github.com/HowardHinnant/papers/blob/master/insert_vs_emplace.html>`_, 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 :option:`ContainersWithPushBack` option.
Before:
.. code-block:: c++
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:
.. code-block:: c++
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 :option:`TupleTypes` option; custom make functions can be modified by the
:option:`TupleMakeFunctions` option.
The other situation is when we pass arguments that will be converted to a type
inside a container.
Before:
.. code-block:: c++
std::vector<boost::optional<std::string> > v;
v.push_back("abc");
After:
.. code-block:: c++
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.
.. code-block:: c++
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 :option:`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 ``new`` expression (to avoid leak)
- if the argument would be converted via derived-to-base cast.
This check requires C++11 or higher to run.
Options
-------
.. option:: ContainersWithPushBack
Semicolon-separated list of class names of custom containers that support
``push_back``.
.. option:: IgnoreImplicitConstructors
When non-zero, the check will ignore implicitly constructed arguments of
``push_back``, e.g.
.. code-block:: c++
std::vector<std::string> v;
v.push_back("a"); // Ignored when IgnoreImplicitConstructors is ``1``.
Default is ``0``.
.. option:: SmartPointers
Semicolon-separated list of class names of custom smart pointers.
.. option:: TupleTypes
Semicolon-separated list of ``std::tuple``-like class names.
.. option:: TupleMakeFunctions
Semicolon-separated list of ``std::make_tuple``-like function names. Those
function calls will be removed from ``push_back`` calls and turned into
``emplace_back``.
Example
^^^^^^^
.. code-block:: c++
std::vector<MyTuple<int, bool, char>> x;
x.push_back(MakeMyTuple(1, false, 'x'));
transforms to:
.. code-block:: c++
std::vector<MyTuple<int, bool, char>> x;
x.emplace_back(1, false, 'x');
when :option:`TupleTypes` is set to ``MyTuple`` and :option:`TupleMakeFunctions`
is set to ``MakeMyTuple``.
|