1. What's the point of using union when we have struct? |
It expresses "I have exactly one of these objects" to the reader. Additionally, it allows particular kinds of memory-oriented optimizations. For example, union is used to seriously improve the performance of standard library components like std::string and std::any, by squeezing the contents of the string into the object and thereby eliminating allocations when the contents are small.
This is called
small buffer optimization. Its particulars are interesting, but not very simple.
It's more important to understand the topic of discriminated unions. You'll write a struct like which contains some kind of flag telling you which variant member of the union is active. In the case of
token, its member of type
kind communicates this information.
(
token is a
union-like class because it contains an unnamed union as a member.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
enum class kind { int_, double_ };
struct token
{
explicit token(int i)
: k_{kind::int_}
, i_{i}
{}
explicit token(double d)
: k_{kind::double_}
, d_{d}
{}
bool is_int() const { return k_ == kind::int_; }
bool is_double() const { return k_ == kind::double_; }
kind get_kind() const { return k_; }
int as_int() const { return i_; };
double as_double() const { return d_; }
private:
union { int i_, double d_; };
kind k_;
};
|
2. In here, the output is 5.But, can I make the output become May?? |
Tell the compiler what it means to say
some_ostream << some_month by defining the following function:
1 2 3 4 5 6 7 8 9
|
std::ostream& operator<< (std::ostream& s, month n)
{
switch (n)
{
case Jan: return s << "Jan";
case Feb: return s << "Feb";
// ... etc.
}
}
|
This is called
operator overloading.
3. In here, I cant even output it now, why is it?? |
Scoped enumerations can't be implicitly converted to (or from) an integer. This makes them a safer choice in most cases; you need to explicitly convert, or follow the previous answer.
|
std::cout << static_cast<int>(k2) << '\n';
|
4. Does it have any effect with adding char (a type) in here?? |
It specifies that the
underlying type of the scoped enumeration is
char.
An object of enumeration type can take all the values of its underlying type (by default). Correspondingly, the size of a scoped enumeration is the size of its underlying type, e.g.,
sizeof (EyeColor) == sizeof (char), and an object of type EyeColor can hold any
char.
There isn't necessarily any benefit to doing this. It does possibly help enable memory optimizations, and it can be used to implement integer-like types with unique behavior.
For example,
std::byte is designed to represent part of another object whose representation we don't know. For example, we can treat an
int as a sequence of
std::byte; but we are forbidden from adding and subtracting bytes.
Its definition is
enum class byte : unsigned char {};
See
https://en.cppreference.com/w/cpp/types/byte