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

Raf*_*cki 4 c++ constructor explicit standards-compliance

请考虑以下代码:

#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.
}
Run Code Online (Sandbox Code Playgroud)

根据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) { }
Run Code Online (Sandbox Code Playgroud)

这种行为是否符合C++标准?对于第一眼看来,它看起来不一致和违反直觉.STL的其他实现是否以相同的方式工作?

Dav*_*eas 5

我不确定我是否理解这个问题,但基本上你是在问为什么std::pair即使实例化类型不能隐式转换,两个不相关的也可以隐式转换.也就是说,为什么实例化类型的隐式可转换属性不会传播到该对.

该标准没有为std::pair模板提供显式赋值运算符,这意味着它将使用隐式生成的赋值运算符.为了能够分配可转换类型对,它依赖于模板化的构造函数,该构造函数允许从到的隐式转换,其行为在§20.2.2[lib.pairs]/4中定义std::pair<A,B>std::pair<C,D>

template<class U, class V> pair(const pair<U, V> &p);
Run Code Online (Sandbox Code Playgroud)

效果:从参数的相应成员初始化成员,根据需要执行隐式转换.

该标准似乎只要求实现使用隐式转换,并且在此特定实现中,转换实际上是显式的,这似乎与标准的措辞相矛盾.