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)
?
答案 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)