string
The assignment operators will set tok
and assign the corresponding member of the union
. Like the destructor, these members must conditionally destroy the string
before assigning a new value to the union
:
Token &Token::operator=(int i)
{
if (tok == STR) sval.~string(); // if we have a string, free it
ival = i; // assign to the appropriate member
tok = INT; // update the discriminant
return *this;
}
If the current value in the union
is a string
, we must destroy that string
before assigning a new value to the union
. We do so by calling the string
destructor. Once we’ve cleaned up the string
member, we assign the given value to the member that corresponds to the parameter type of the operator. In this case, our parameter is an int
, so we assign to ival
. We update the discriminant and return.
The double
and char
assignment operators behave identically to the int
version and are left as an exercise. The string
version differs from the others because it must manage the transition to and from the string
type:
Token &Token::operator=(const std::string &s)
{
if (tok == STR) // if we already hold a string, just do an assignment
sval = s;
else
new(&sval) string(s); // otherwise construct a string
tok = STR; // update the discriminant
return *this;
}
In this case, if the union
already holds a string
, we can use the normal string
assignment operator to give a new value to that string
. Otherwise, there is no existing string
object on which to invoke the string
assignment operator. Instead, we must construct a string
in the memory that holds the union
. We do so using placement new
(§ 19.1.2, p. 824) to construct a string
at the location in which sval
resides. We initialize that string
as a copy of our string
parameter. We next update the discriminant and return.