Why std :: pair
has a custom assignment operator, and does not use Default
version?
code from libC++
just makes the soil assignment, which would have done a default operator:
_ libcpp_inline_visibility
Pair & amp; Operator = (TypeName Conditional & LT;
is_copy_assignable & lt; first_type & gt; :: value & amp; & amp;
is_copy_assignable & lt; Second_Type & gt; :: Value,
Pair, __nat & gt; :: Type Const & amp; __p)
_Nothrow_copy_assignable & lt; first_type & gt; :: Value & amp; & amp;
is_nothrow_copy_assignable & lt; Second_Type & GT; :: Value)
{
first = __p.first;
Second = __p.second;
RETURN * THIS;
}
Copy constructor, for example, uses default implementation, so this is not Code Style:
pair (pair const & amp;) = default;
Answer 1, Authority 100%
In the language standard, this operator is declared explicitly. If you look at a note to this operator, then it says
Remarks: This operator is defined as deleted unless
is_copy_assignable_v & lt; first_type & gt;
isTrue
andis_copy_assignable_v & lt; second_type & gt;
isTrue
.
That is, the arguments of the template must satisfy the requirements of std :: is_copy_assignable
.
std :: is_copy_assignable
requires the first argument to be assigned from the constant second: std :: is_assignable & lt; t & amp;, const t & amp; & gt;
.
In turn, STD :: IS_ASSIGNABLE
Must give True
if the expression STD :: DECLVAL & LT; T & GT; () = STD :: DECLVAL & LT; U & GT ; ()
is compiled, i.e. Object type T
You can assign an object like U
.
i.e. The following code should not be compiled:
std :: pair & lt; int [4], int & gt; P1;
STD :: PAIR & LT; INT [4], int & gt; P2;
p2 = p1; // should be a mistake
So, if you leave the default statement, it will not be errors. Let’s make imitation on your own class:
template & lt; TypeName T & GT;
Struct Tester.
{
Tester & amp; operator = (Tester Const & amp;) = Default;
T mem;
};
TESTER & LT; INT [4] & gt; P1;
TESTER & LT; INT [4] & gt; P2;
p2 = p1; // no error
Using Type = int [4];
static_assert (std :: is_copy_assignable_v & lt; type & gt;, ""); // Error
As we see, the error is missing, although static_assert
shows that the int [4]
type does not satisfy the requirements of is_copy_assignable
.
Therefore, an implicitly generated assignment operator is not suitable.
However, already explicitly written operator passes our test and we get an error when assigning arrays.
tester & amp; Operator = (Tester Const & Amp; RHV)
{
mem = rhv.mem;
RETURN * THIS;
}
Additionally, you need to “hang out” the compilation time checks, as is done in the example given in the question.
Answer 2, Authority 40%
In order for the assignment operator to work even with types, instantiated links.
# include & lt; iostream & gt;
TEMPLATE & LT; Class T1, Class T2 & GT;
STRUCT PAIR {
T1 FIRST;
T2 Second;
// Pair & amp; Operator = (Const Pair & amp;) = default; // 1
Pair & amp; Operator = (Const Pair & amp; RHS) {// 2
first = rhs.first;
Second = Rhs.second;
RETURN * THIS;
}
};
INT MAIN () {
int x = 1, y = 2;
pair & lt; int & amp;, int & gt; p1 {x, y}, p2 {y, x};
p1 = p2;
STD :: COUT & LT; & LT; p1.first & lt; & lt; p1.second & lt; & lt; p2.first & lt; & lt; p2.second & lt; & lt; '\ n';
}
If you comment out 2 here and uncomment 1, it won’t work, but now it does.