xref: /llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst (revision 0e325081192be951a9d54bb246ef030c37bffd21)
1.. title:: clang-tidy - bugprone-forwarding-reference-overload
2
3bugprone-forwarding-reference-overload
4======================================
5
6The check looks for perfect forwarding constructors that can hide copy or move
7constructors. If a non const lvalue reference is passed to the constructor, the
8forwarding reference parameter will be a better match than the const reference
9parameter of the copy constructor, so the perfect forwarding constructor will be
10called, which can be confusing.
11For detailed description of this issue see: Scott Meyers, Effective Modern C++,
12Item 26.
13
14Consider the following example:
15
16.. code-block:: c++
17
18    class Person {
19    public:
20      // C1: perfect forwarding ctor
21      template<typename T>
22      explicit Person(T&& n) {}
23
24      // C2: perfect forwarding ctor with parameter default value
25      template<typename T>
26      explicit Person(T&& n, int x = 1) {}
27
28      // C3: perfect forwarding ctor guarded with enable_if
29      template<typename T, typename X = enable_if_t<is_special<T>, void>>
30      explicit Person(T&& n) {}
31
32      // C4: variadic perfect forwarding ctor guarded with enable_if
33      template<typename... A,
34        enable_if_t<is_constructible_v<tuple<string, int>, A&&...>, int> = 0>
35      explicit Person(A&&... a) {}
36
37      // C5: perfect forwarding ctor guarded with requires expression
38      template<typename T>
39      requires requires { is_special<T>; }
40      explicit Person(T&& n) {}
41
42      // C6: perfect forwarding ctor guarded with concept requirement
43      template<Special T>
44      explicit Person(T&& n) {}
45
46      // (possibly compiler generated) copy ctor
47      Person(const Person& rhs);
48    };
49
50The check warns for constructors C1 and C2, because those can hide copy and move
51constructors. We suppress warnings if the copy and the move constructors are both
52disabled (deleted or private), because there is nothing the perfect forwarding
53constructor could hide in this case. We also suppress warnings for constructors
54like C3-C6 that are guarded with an ``enable_if`` or a concept, assuming the
55programmer was aware of the possible hiding.
56
57Background
58----------
59
60For deciding whether a constructor is guarded with enable_if, we consider the
61types of the constructor parameters, the default values of template type parameters
62and the types of non-type template parameters with a default literal value. If any
63part of these types is ``std::enable_if`` or ``std::enable_if_t``, we assume the
64constructor is guarded.
65
66