1.. title:: clang-tidy - bugprone-move-forwarding-reference 2 3bugprone-move-forwarding-reference 4================================== 5 6Warns if ``std::move`` is called on a forwarding reference, for example: 7 8.. code-block:: c++ 9 10 template <typename T> 11 void foo(T&& t) { 12 bar(std::move(t)); 13 } 14 15`Forwarding references 16<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4164.pdf>`_ should 17typically be passed to ``std::forward`` instead of ``std::move``, and this is 18the fix that will be suggested. 19 20(A forwarding reference is an rvalue reference of a type that is a deduced 21function template argument.) 22 23In this example, the suggested fix would be 24 25.. code-block:: c++ 26 27 bar(std::forward<T>(t)); 28 29Background 30---------- 31 32Code like the example above is sometimes written with the expectation that 33``T&&`` will always end up being an rvalue reference, no matter what type is 34deduced for ``T``, and that it is therefore not possible to pass an lvalue to 35``foo()``. However, this is not true. Consider this example: 36 37.. code-block:: c++ 38 39 std::string s = "Hello, world"; 40 foo(s); 41 42This code compiles and, after the call to ``foo()``, ``s`` is left in an 43indeterminate state because it has been moved from. This may be surprising to 44the caller of ``foo()`` because no ``std::move`` was used when calling 45``foo()``. 46 47The reason for this behavior lies in the special rule for template argument 48deduction on function templates like ``foo()`` -- i.e. on function templates 49that take an rvalue reference argument of a type that is a deduced function 50template argument. (See section [temp.deduct.call]/3 in the C++11 standard.) 51 52If ``foo()`` is called on an lvalue (as in the example above), then ``T`` is 53deduced to be an lvalue reference. In the example, ``T`` is deduced to be 54``std::string &``. The type of the argument ``t`` therefore becomes 55``std::string& &&``; by the reference collapsing rules, this collapses to 56``std::string&``. 57 58This means that the ``foo(s)`` call passes ``s`` as an lvalue reference, and 59``foo()`` ends up moving ``s`` and thereby placing it into an indeterminate 60state. 61