The specification of the copy semantics of the C++03 version of std::pair is defined by the class synopsis in [lib.pairs]:
template <class T1, class T2> struct pair { typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; pair(); pair(const T1& x, const T2& y); template<class U, class V> pair(const pair<U, V> &p); };
The effect of this specification is, that the copy constructor is compiler-declared with the proper form depending on the contained member types. In particular, the instantiation of pair is well-formed with an element type that has a copy constructor with non-const first parameter type like specialzations of auto_ptr or any user-defined type like the following one:
struct A { A(A&){} };
In contrast to container types which require CopyConstructible value types, the C++03 pair does support these, albeit unusual, element types.
The FDIS version of the std::pair specification does specify the same semantics by defaulting the copy and move constructor in [pairs.pair]:
template <class T1, class T2> struct pair { typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; pair(const pair&) = default; pair(pair&&) = default; pair(); […] };
But according to the current core rules this makes the instantiation of e.g. std::pair<A, int> ill-formed, because of the const mismatch of the compiler-declared form of the copy constructor with that of the defaulted declaration.
Unfortunately there seems to be no simple library solution for this problem. If the defaulted declarations were removed, both copy c'tor and move c'tor would be deleted, because there exist user-declared copy assignment and move assignment operators in the FDIS. But these operations need to be user-defined to realize the wanted semantics of these operations for element types that are reference types. If core rules would not be changed to fix that, I see the following options:
This problem does not extend as backward-compatibility problem to tuple, because the TR1 specification did explicitly declare copy constructor and copy assignment operator via the "normal" form:
tuple(const tuple&); tuple& operator=(const tuple&);