forked from OSchip/llvm-project
57 lines
2.1 KiB
ReStructuredText
57 lines
2.1 KiB
ReStructuredText
.. title:: clang-tidy - bugprone-forwarding-reference-overload
|
|
|
|
bugprone-forwarding-reference-overload
|
|
======================================
|
|
|
|
The check looks for perfect forwarding constructors that can hide copy or move
|
|
constructors. If a non const lvalue reference is passed to the constructor, the
|
|
forwarding reference parameter will be a better match than the const reference
|
|
parameter of the copy constructor, so the perfect forwarding constructor will be
|
|
called, which can be confusing.
|
|
For detailed description of this issue see: Scott Meyers, Effective Modern C++,
|
|
Item 26.
|
|
|
|
Consider the following example:
|
|
|
|
.. code-block:: c++
|
|
|
|
class Person {
|
|
public:
|
|
// C1: perfect forwarding ctor
|
|
template<typename T>
|
|
explicit Person(T&& n) {}
|
|
|
|
// C2: perfect forwarding ctor with parameter default value
|
|
template<typename T>
|
|
explicit Person(T&& n, int x = 1) {}
|
|
|
|
// C3: perfect forwarding ctor guarded with enable_if
|
|
template<typename T, typename X = enable_if_t<is_special<T>, void>>
|
|
explicit Person(T&& n) {}
|
|
|
|
// C4: variadic perfect forwarding ctor guarded with enable_if
|
|
template<typename... A,
|
|
enable_if_t<is_constructible_v<tuple<string, int>, A&&...>, int> = 0>
|
|
explicit Person(A&&... a) {}
|
|
|
|
// (possibly compiler generated) copy ctor
|
|
Person(const Person& rhs);
|
|
};
|
|
|
|
The check warns for constructors C1 and C2, because those can hide copy and move
|
|
constructors. We suppress warnings if the copy and the move constructors are both
|
|
disabled (deleted or private), because there is nothing the perfect forwarding
|
|
constructor could hide in this case. We also suppress warnings for constructors
|
|
like C3 and C4 that are guarded with an ``enable_if``, assuming the programmer was
|
|
aware of the possible hiding.
|
|
|
|
Background
|
|
----------
|
|
|
|
For deciding whether a constructor is guarded with enable_if, we consider the
|
|
types of the constructor parameters, the default values of template type parameters
|
|
and the types of non-type template parameters with a default literal value. If any
|
|
part of these types is ``std::enable_if`` or ``std::enable_if_t``, we assume the
|
|
constructor is guarded.
|
|
|