In addition to the copy- and move-assignment operators that assign one object of the class type to another object of the same type (§ 13.1.2, p. 500, and § 13.6.2, p. 536), a class can define additional assignment operators that allow other types as the right-hand operand.
As one example, in addition to the copy- and move-assignment operators, the library vector
class defines a third assignment operator that takes a braced list of elements (§ 9.2.5, p. 337). We can use this operator as follows:
vector<string> v;
v = {"a", "an", "the"};
We can add this operator to our StrVec
class (§ 13.5, p. 526) as well:
class StrVec {
public:
StrVec &operator=(std::initializer_list<std::string>);
// other members as in § 13.5 (p. 526)
};
To be consistent with assignment for the built-in types (and with the copy- and move-assignment operators we already defined), our new assignment operator will return a reference to its left-hand operand:
StrVec &StrVec::operator=(initializer_list<string> il)
{
// alloc_n_copy allocates space and copies elements from the given range
auto data = alloc_n_copy(il.begin(), il.end());
free(); // destroy the elements in this object and free the space
elements = data.first; // update data members to point to the new space
first_free = cap = data.second;
return *this;
}
As with the copy- and move-assignment operators, other overloaded assignment operators have to free the existing elements and create new ones. Unlike the copy-and move-assignment operators, this operator does not need to check for self-assignment. The parameter is an initializer_list<string>
(§ 6.2.6, p. 220), which means that il
cannot be the same object as the one denoted by this
.
Assignment operators can be overloaded. Assignment operators, regardless of parameter type, must be defined as member functions.
Compound assignment operators are not required to be members. However, we prefer to define all assignments, including compound assignments, in the class. For consistency with the built-in compound assignment, these operators should return a reference to their left-hand operand. For example, here is the definition of the Sales_data
compound-assignment operator:
// member binary operator: left-hand operand is bound to the implicit this pointer
// assumes that both objects refer to the same book
Sales_data& Sales_data::operator+=(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
Assignment operators must, and ordinarily compound-assignment operators should, be defined as members. These operators should return a reference to the left-hand operand.