关于 pair 数据结构的相关构造函数的疑问?
wchzh opened this issue · 4 comments
wchzh commented
对于已经定义了下面的copy构造函数:
// implicit constructiable for other pair
template <class Other1, class Other2,
typename std::enable_if<
std::is_constructible<Ty1, const Other1&>::value &&
std::is_constructible<Ty2, const Other2&>::value &&
std::is_convertible<const Other1&, Ty1>::value &&
std::is_convertible<const Other2&, Ty2>::value, int>::type = 0>
constexpr pair(const pair<Other1, Other2>& other)
: first(other.first),
second(other.second)
{
}
为什么还要定义explicit的copy构造函数:
// explicit constructiable for other pair
template <class Other1, class Other2,
typename std::enable_if<
std::is_constructible<Ty1, const Other1&>::value &&
std::is_constructible<Ty2, const Other2&>::value &&
(!std::is_convertible<const Other1&, Ty1>::value ||
!std::is_convertible<const Other2&, Ty2>::value), int>::type = 0>
explicit constexpr pair(const pair<Other1, Other2>& other)
: first(other.first),
second(other.second)
{
}
我理解模板参数的含义,就是不知道为什么这样定义,或者可以指出在什么情况下才会调用下面的 explicit的copy构造函数吗。谁能帮忙解答下?谢谢。
frederick-vs-ja commented
首先这不是复制构造函数。
两个重载所要表达的是:如果 Other1
到 Ty1
和 Other2
到 Ty2
存在隐式转换,才提供前一个重载使得 pair<Other1, Other2>
能隐式转换成 pair<T1, T2>
。否则 pair<T1, T2>
只能从 pair<Other1, Other2>
显式构造。
这种设计的目的是避免意外地引入“使用隐式转换的方式进行了本来要求为显式的转换”,参见 N4387 。
NingKobe commented
萌新求问大佬,为什么要用U替换掉Ty,直接用Ty不是也可以判断是否可以拷贝构造吗?还有pair参数是Ty,U不是一定等于Ty吗,为什么还要判断是否可以隐式转换呢?
// implicit constructiable for this type
template <class U1 = Ty1, class U2 = Ty2,
typename std::enable_if<
std::is_copy_constructible<U1>::value&&
std::is_copy_constructible<U2>::value&&
std::is_convertible<const U1&, Ty1>::value&&
std::is_convertible<const U2&, Ty2>::value, int>::type = 0>
constexpr pair(const Ty1& a, const Ty2& b)
: first(a), second(b)
{
}
// explicit constructible for this type
template <class U1 = Ty1, class U2 = Ty2,
typename std::enable_if<
std::is_copy_constructible<U1>::value&&
std::is_copy_constructible<U2>::value &&
(!std::is_convertible<const U1&, Ty1>::value ||
!std::is_convertible<const U2&, Ty2>::value), int>::type = 0>
explicit constexpr pair(const Ty1& a, const Ty2& b)
: first(a), second(b)
{
}
frederick-vs-ja commented
萌新求问大佬,为什么要用U替换掉Ty,直接用Ty不是也可以判断是否可以拷贝构造吗?还有pair参数是Ty,U不是一定等于Ty吗,为什么还要判断是否可以隐式转换呢?
- 只有在模板头引入的模板形参带来的替换失败才不是错误。
is_convertible<T, T>::value
不一定对所有对象类型均为true
,例如Ty
可以是不支持复制和移动构造的类或是数组。
NingKobe commented
萌新求问大佬,为什么要用U替换掉Ty,直接用Ty不是也可以判断是否可以拷贝构造吗?还有pair参数是Ty,U不是一定等于Ty吗,为什么还要判断是否可以隐式转换呢?
- 只有在模板头引入的模板形参带来的替换失败才不是错误。
is_convertible<T, T>::value
不一定对所有对象类型均为true
,例如Ty
可以是不支持复制和移动构造的类或是数组。
非常感谢大佬的回答!如拨云见日,茅塞顿开!让我自己怎么也想不出来😂
所以我自己也试了一下,写了一个简单的例子,如果没有用U替换Ty的话,即使没用到这个函数(下面类A中的f)也会编译报错
template <class T>
class A {
public:
template <class U = T, typename std::enable_if<std::is_copy_assignable<U>::value, int>::type = 0>
void f() {
cout<<"!"<<endl;
}
};