在轉發參考上過載
提供轉發引用過載時必須非常小心,因為它可能匹配得太好了:
struct A {
    A() = default;           // #1
    A(A const& ) = default;  // #2
    template <class T>
    A(T&& );                 // #3
};
這裡的意圖是 A 是可複製的,並且我們有另一個可能初始化其他成員的建構函式。然而:
A a;     // calls #1
A b(a);  // calls #3!
建築呼叫有兩個可行的匹配:
A(A const& ); // #2
A(A& );       // #3, with T = A&
兩者都是精確匹配,但是 #3 引用了比 #2 更少的 cv 資格物件,因此它具有更好的標準轉換序列並且是最好的可行功能。
這裡的解決方案是始終約束這些建構函式(例如使用 SFINAE):
template <class T,
    class = std::enable_if_t<!std::is_convertible<std::decay_t<T>*, A*>::value>
    >
A(T&& );
這裡的型別特徵是從考慮中公開且明確地從 A 中排除任何 A 或類,這將使得該建構函式在前面描述的示例中形成錯誤(並因此從過載集中移除)。結果,呼叫了複製建構函式 - 這就是我們想要的。