192 lines · plain
1.. title:: clang-tidy - modernize-use-emplace2 3modernize-use-emplace4=====================5 6The check flags insertions to an STL-style container done by calling the7``push_back``, ``push``, or ``push_front`` methods with an8explicitly-constructed temporary of the container element type. In this case,9the corresponding ``emplace`` equivalent methods result in less verbose and10potentially more efficient code. Right now the check doesn't support11``insert``. It also doesn't support ``insert`` functions for associative12containers because replacing ``insert`` with ``emplace`` may result in13`speed regression <https://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.14 15The :option:`ContainersWithPushBack`, :option:`ContainersWithPush`, and16:option:`ContainersWithPushFront` options are used to specify the container17types that support the ``push_back``, ``push``, and ``push_front`` operations18respectively. The default values for these options are as follows:19 20* :option:`ContainersWithPushBack`: ``std::vector``, ``std::deque``,21 and ``std::list``.22* :option:`ContainersWithPush`: ``std::stack``, ``std::queue``,23 and ``std::priority_queue``.24* :option:`ContainersWithPushFront`: ``std::forward_list``,25 ``std::list``, and ``std::deque``.26 27This check also reports when an ``emplace``-like method is improperly used,28for example using ``emplace_back`` while also calling a constructor. This29creates a temporary that requires at best a move and at worst a copy. Almost30all ``emplace``-like functions in the STL are covered by this, with31``try_emplace`` on ``std::map`` and ``std::unordered_map`` being the32exception as it behaves slightly differently than all the others. More33containers can be added with the :option:`EmplacyFunctions` option, so long34as the container defines a ``value_type`` type, and the ``emplace``-like35functions construct a ``value_type`` object.36 37Before:38 39.. code-block:: c++40 41 std::vector<MyClass> v;42 v.push_back(MyClass(21, 37));43 v.emplace_back(MyClass(21, 37));44 45 std::vector<std::pair<int, int>> w;46 47 w.push_back(std::pair<int, int>(21, 37));48 w.push_back(std::make_pair(21L, 37L));49 w.emplace_back(std::make_pair(21L, 37L));50 51After:52 53.. code-block:: c++54 55 std::vector<MyClass> v;56 v.emplace_back(21, 37);57 v.emplace_back(21, 37);58 59 std::vector<std::pair<int, int>> w;60 w.emplace_back(21, 37);61 w.emplace_back(21L, 37L);62 w.emplace_back(21L, 37L);63 64By default, the check is able to remove unnecessary ``std::make_pair`` and65``std::make_tuple`` calls from ``push_back`` calls on containers of66``std::pair`` and ``std::tuple``. Custom tuple-like types can be modified by67the :option:`TupleTypes` option; custom make functions can be modified by the68:option:`TupleMakeFunctions` option.69 70The other situation is when we pass arguments that will be converted to a type71inside a container.72 73Before:74 75.. code-block:: c++76 77 std::vector<boost::optional<std::string> > v;78 v.push_back("abc");79 80After:81 82.. code-block:: c++83 84 std::vector<boost::optional<std::string> > v;85 v.emplace_back("abc");86 87 88In some cases the transformation would be valid, but the code wouldn't be89exception safe. In this case the calls of ``push_back`` won't be replaced.90 91.. code-block:: c++92 93 std::vector<std::unique_ptr<int>> v;94 v.push_back(std::unique_ptr<int>(new int(0)));95 auto *ptr = new int(1);96 v.push_back(std::unique_ptr<int>(ptr));97 98This is because replacing it with ``emplace_back`` could cause a leak of this99pointer if ``emplace_back`` would throw exception before emplacement (e.g. not100enough memory to add a new element).101 102For more info read item 42 - "Consider emplacement instead of insertion." of103Scott Meyers "Effective Modern C++".104 105The default smart pointers that are considered are ``std::unique_ptr``,106``std::shared_ptr``, ``std::auto_ptr``. To specify other smart pointers or107other classes use the :option:`SmartPointers` option.108 109 110Check also doesn't fire if any argument of the constructor call would be:111 112 - a bit-field (bit-fields can't bind to rvalue/universal reference)113 114 - a ``new`` expression (to avoid leak)115 116 - if the argument would be converted via derived-to-base cast.117 118This check requires C++11 or higher to run.119 120Options121-------122 123.. option:: ContainersWithPushBack124 125 Semicolon-separated list of class names of custom containers that support126 ``push_back``.127 128.. option:: ContainersWithPush129 130 Semicolon-separated list of class names of custom containers that support131 ``push``.132 133.. option:: ContainersWithPushFront134 135 Semicolon-separated list of class names of custom containers that support136 ``push_front``.137 138.. option:: IgnoreImplicitConstructors139 140 When `true`, the check will ignore implicitly constructed arguments of141 ``push_back``, e.g.142 143 .. code-block:: c++144 145 std::vector<std::string> v;146 v.push_back("a"); // Ignored when IgnoreImplicitConstructors is `true`.147 148 Default is `false`.149 150.. option:: SmartPointers151 152 Semicolon-separated list of class names of custom smart pointers.153 154.. option:: TupleTypes155 156 Semicolon-separated list of ``std::tuple``-like class names.157 158.. option:: TupleMakeFunctions159 160 Semicolon-separated list of ``std::make_tuple``-like function names. Those161 function calls will be removed from ``push_back`` calls and turned into162 ``emplace_back``.163 164.. option:: EmplacyFunctions165 166 Semicolon-separated list of containers without their template parameters167 and some ``emplace``-like method of the container. Example:168 ``vector::emplace_back``. Those methods will be checked for improper use and169 the check will report when a temporary is unnecessarily created. All STL170 containers with such member functions are supported by default.171 172Example173^^^^^^^174 175.. code-block:: c++176 177 std::vector<MyTuple<int, bool, char>> x;178 x.push_back(MakeMyTuple(1, false, 'x'));179 x.emplace_back(MakeMyTuple(1, false, 'x'));180 181transforms to:182 183.. code-block:: c++184 185 std::vector<MyTuple<int, bool, char>> x;186 x.emplace_back(1, false, 'x');187 x.emplace_back(1, false, 'x');188 189when :option:`TupleTypes` is set to ``MyTuple``, :option:`TupleMakeFunctions`190is set to ``MakeMyTuple``, and :option:`EmplacyFunctions` is set to191``vector::emplace_back``.192