模板构造函数的重载解析

Overload Resolution with Template Constructor?

本文关键字:重载 构造函数      更新时间:2023-10-16
struct X
{
    X(X&);         // (1)
    X(X&&);        // (2)
    X(const X&);   // (3)
    X(const X&&);  // (4)
};

考虑所有可能的 X 用法的集合 U,其中这四个构造函数中的一个将被绑定和调度。

例如,U 的一个元素是:

int main()
{
    X x1 = ...;
    X x2(x1);  // <-- (1) used
}

现在假设我们添加第五个构造函数,如下所示:

struct X
{
    X(X&);                    // (1)
    X(X&&);                   // (2)
    X(const X&);              // (3)
    X(const X&&);             // (4)
    template<class T> X(T&&); // (5)
};

是否有任何新的重载分辨率,其中 U 的一个元素现在将作为更好的匹配调度到(5),而不是像以前那样(1)(2)(3)(4)

考虑派生类:

struct Y : X
{ Y() { } };
int main()
{
  Y y;
  X x1(y); // derived class
}

好的,我现在明白了。我想,这种情况适用于任何可转换为 X 的 T。例如:

struct R
{
 operator X() const;
};
int main()
{
  R r{};
  X x{r};
}

如果您的目标是拥有一个仅处理您的 (1( 到 (4( 但不包含其他任何内容的模板构造函数,则必须通过以下方式"消除"其他构造函数:

template <typename T, typename U>
constexpr bool IsSame() {
  return is_same<
    typename decay<T>::type, 
    typename decay<U>::type
  >::value;
}
struct X
{
  template <class T, typename enable_if<IsSame<T, X>()>::type* = 0> 
  X(T&&);
};

或者,如果您的目标是将 T 的可转换为 X 与其他 T 区分开来,请考虑以下解决方案:

struct X
{
  template <
    class T, 
    typename enable_if<is_convertible<T, X>::value>::type* = 0
  > 
  X(T&&); // do something
  template <
    class T, 
    typename enable_if<!is_convertible<T, X>::value>::type* = 0
  > 
  X(T&&); // do something else
};
int main()
{
    X x2(12);  // <-- (5) used
}

(T 被推导为 int(