为什么std :: pair在赋值时调用显式构造函数

时间:2011-07-20 10:46:15

标签: c++ constructor standards-compliance explicit

请考虑以下代码:

#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的其他实现是否以相同的方式工作?

4 个答案:

答案 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>的转换构造函数。这适用于firstsecond成员可转换为另一对的相应成员的情况。

根据标准分别转换每个成员。

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

但由于35是整数,我们正在尝试将std::pair<int, int>分配给std::pair<long, long>。如果没有模板化构造函数和模板化赋值运算符,它将会失败,因为MyPair已经证明了。

所以回答你的问题:模板化的构造函数是为了方便。每个人都希望能够为长期分配一个int。因此能够分配例如是合理的。对一对长的一对。。