| 12
 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
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 
 | .. 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 <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.
By default only ``std::vector``, ``std::deque``, ``std::list`` are considered.
This list can be modified using the :option:`ContainersWithPushBack` option.
This check also reports when an ``emplace``-like method is improperly used,
for example using ``emplace_back`` while also calling a constructor. This
creates a temporary that requires at best a move and at worst a copy. Almost all
``emplace``-like functions in the STL are covered by this, with ``try_emplace``
on ``std::map`` and ``std::unordered_map`` being the exception as it behaves
slightly differently than all the others. More containers can be added with the
:option:`EmplacyFunctions` option, so long as the container defines a
``value_type`` type, and the ``emplace``-like functions construct a
``value_type`` object.
Before:
.. code-block:: c++
    std::vector<MyClass> v;
    v.push_back(MyClass(21, 37));
    v.emplace_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));
    w.emplace_back(std::make_pair(21L, 37L));
After:
.. code-block:: c++
    std::vector<MyClass> v;
    v.emplace_back(21, 37);
    v.emplace_back(21, 37);
    std::vector<std::pair<int, int>> w;
    w.emplace_back(21, 37);
    w.emplace_back(21L, 37L);
    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 `true`, 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 `true`.
    Default is `false`.
.. 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``.
.. option:: EmplacyFunctions
    Semicolon-separated list of containers without their template parameters
    and some ``emplace``-like method of the container. Example:
    ``vector::emplace_back``. Those methods will be checked for improper use and
    the check will report when a temporary is unnecessarily created.
Example
^^^^^^^
.. code-block:: c++
  std::vector<MyTuple<int, bool, char>> x;
  x.push_back(MakeMyTuple(1, false, 'x'));
  x.emplace_back(MakeMyTuple(1, false, 'x'));
transforms to:
.. code-block:: c++
  std::vector<MyTuple<int, bool, char>> x;
  x.emplace_back(1, false, 'x');
  x.emplace_back(1, false, 'x');
when :option:`TupleTypes` is set to ``MyTuple``, :option:`TupleMakeFunctions`
is set to ``MakeMyTuple``, and :option:`EmplacyFunctions` is set to
``vector::emplace_back``.
 |