使用模板构造函数重载解决方案?

时间:2012-12-31 10:47:29

标签: c++ c++11

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)

3 个答案:

答案 0 :(得分:4)

考虑派生类:

struct Y : X
{ Y() { } };

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

答案 1 :(得分:2)

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

struct R
{
 operator X() const;
};

int main()
{
  R r{};
  X x{r};
}

如果你的目标是让一个模板构造函数只处理你的(1)到(4),那么你不得不通过类似的东西来“SFINAE”去除其他东西:

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
};

答案 2 :(得分:-1)

int main()
{
    X x2(12);  // <-- (5) used
}

(T推断为int)