Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于 pair 数据结构的相关构造函数的疑问? #119

Open
wchzh opened this issue Dec 13, 2022 · 4 comments
Open

关于 pair 数据结构的相关构造函数的疑问? #119

wchzh opened this issue Dec 13, 2022 · 4 comments

Comments

@wchzh
Copy link

wchzh commented Dec 13, 2022

对于已经定义了下面的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
Copy link
Contributor

首先这不是复制构造函数。

两个重载所要表达的是:如果 Other1Ty1Other2Ty2 存在隐式转换,才提供前一个重载使得 pair<Other1, Other2> 能隐式转换成 pair<T1, T2>。否则 pair<T1, T2> 只能从 pair<Other1, Other2> 显式构造。

这种设计的目的是避免意外地引入“使用隐式转换的方式进行了本来要求为显式的转换”,参见 N4387

@NingKobe
Copy link

NingKobe commented Feb 18, 2023

萌新求问大佬,为什么要用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
Copy link
Contributor

萌新求问大佬,为什么要用U替换掉Ty,直接用Ty不是也可以判断是否可以拷贝构造吗?还有pair参数是Ty,U不是一定等于Ty吗,为什么还要判断是否可以隐式转换呢?

  1. 只有在模板头引入的模板形参带来的替换失败才不是错误。
  2. is_convertible<T, T>::value 不一定对所有对象类型均为 true ,例如 Ty 可以是不支持复制和移动构造的类或是数组。

@NingKobe
Copy link

NingKobe commented Mar 8, 2023

萌新求问大佬,为什么要用U替换掉Ty,直接用Ty不是也可以判断是否可以拷贝构造吗?还有pair参数是Ty,U不是一定等于Ty吗,为什么还要判断是否可以隐式转换呢?

  1. 只有在模板头引入的模板形参带来的替换失败才不是错误。
  2. 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;
	}
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants