请考虑以下代码:
#include<iostream>
#include<utility>
struct Base
{
int baseint;
};
struct Der1 : Base
{
int der1int;
Der1() : der1int(1) {}
explicit Der1(const Base& a) : Base(a), der1int(1)
{
std::cerr << "cc1" << std::endl;
}
};
struct Der2 : Base
{
int der2int;
Der2() : der2int(2) {}
explicit Der2(const Base& a) : Base(a), der2int(2)
{
std::cerr << "cc2" << std::endl;
}
};
template <typename T, typename U>
struct MyPair
{
T first;
U second;
};
int main()
{
Der1 d1;
Der2 d2;
std::pair<Der1, int> p1;
std::pair<Der2, int> p2;
p1 = p2; // This compiles successfully
MyPair<Der1, int> mp1;
MyPair<Der2, int> mp2;
mp1 = mp2; // This will raise compiler error, as expected.
}
根据GCC 4.5.2进行测试
原因在于std::pair
来源:
/** There is also a templated copy ctor for the @c pair class itself. */
template<class _U1, class _U2>
pair(const pair<_U1, _U2>& __p)
: first(__p.first),
second(__p.second) { }
该行为是否符合C ++标准?对于第一眼看来,它看起来不一致和违反直觉。 STL的其他实现是否以相同的方式工作?
答案 0 :(得分:5)
答案 1 :(得分:2)
作为类std :: pair的一部分构造函数
template<class T1, T2>
class pair
{
public:
template<class _U1, class _U2>
pair(const pair<_U1, _U2>& __p)
: first(__p.first),
second(__p.second)
{ }
};
不是复制构造函数,而是从任何pair<_U1, _U2>
到pair<T1, T2>
的转换构造函数。这适用于first
和second
成员可转换为另一对的相应成员的情况。
根据标准分别转换每个成员。
答案 2 :(得分:1)
这应该是一个评论,但我更喜欢一些空间来输入它。
所以,我们可以说有两种类型:
typedef std::pair<A,B> pairAB;
typedef std::pair<S,T> pairST;
现在我想将一个分配给另一个:
pairAB x;
pairST w;
x = w; // how?
由于std::pair
没有明确的分配运算符,我们只能使用默认赋值pairAB & operator=(const pairAB &)
。因此,我们调用隐式转换构造函数,它相当于:
x = pairAB(w); // this happens when we say "x = w;"
但是,有人指出,此转换构造函数调用显式成员构造函数:
pairAB(const pairST & other) : first(other.first), second(other.second) { }
因此,对于每个成员,我们都使用显式转换。
答案 3 :(得分:0)
快速回答:因为标准说它应该。
你的下一个问题当然是:为什么标准会这样说?
想象一下这一行,我认为你同意应该这样做:
std::pair<long, long> x = std::make_pair(3, 5);
但由于3
和5
是整数,我们正在尝试将std::pair<int, int>
分配给std::pair<long, long>
。如果没有模板化构造函数和模板化赋值运算符,它将会失败,因为MyPair
已经证明了。
所以回答你的问题:模板化的构造函数是为了方便。每个人都希望能够为长期分配一个int。因此能够分配例如是合理的。对一对长的一对。。