Operator overloading allows you to redefine the way operators work with user-defined types like classes and enums. This chapter covers how to overload operators for custom types, with examples including enums and I/O stream operations.
#include <iostream>
#include <string_view>
#include <optional>
enum Color
{
black,
red,
blue,
};
constexpr std::string_view getColorName(Color color)
{
switch (color)
{
case black: return "black";
case red: return "red";
case blue: return "blue";
default: return "???";
}
}
enum Pet
{
cat,
dog,
pig,
whale,
};
constexpr std::optional<Pet> getPetFromString(std::string_view sv)
{
if (sv == "cat") return cat;
if (sv == "dog") return dog;
if (sv == "pig") return pig;
if (sv == "whale") return whale;
return {};
}
operator<<
for OutputTo overload the <<
operator for output, we define a function that takes an std::ostream
reference and an enum value.
// Teach operator<< how to print a Color
std::ostream& operator<<(std::ostream& out, Color color)
{
out << getColorName(color); // print our color's name to whatever output stream out
return out; // operator<< conventionally returns its left operand
}
operator>>
for InputTo overload the >>
operator for input, we define a function that takes an std::istream
reference and an enum reference.
// pet is an in/out parameter
std::istream& operator>>(std::istream& in, Pet& pet)
{
std::string s{};
in >> s; // get input string from user
std::optional<Pet> match { getPetFromString(s) };
if (match) // if we found a match
{
pet = *match; // set Pet to the matching enumerator
return in;
}
// We didn't find a match, so input must have been invalid
// so we will set input stream to fail state
in.setstate(std::ios_base::failbit);
// On an extraction failure, operator>> zero-initializes fundamental types
// Uncomment the following line to make this operator do the same thing
// pet = {};
return in;
}
The main function demonstrates how to use the overloaded operators.
int main()
{
Color shirt{ blue };
std::cout << "Your shirt is " << shirt << '\n'; // it works!
std::cout << "Enter a pet: cat, dog, pig, or whale: ";
Pet pet{};
std::cin >> pet;
if (std::cin) // if we found a match
std::cout << "You chose: " << getPetName(pet) << '\n';
else
{
std::cin.clear(); // reset the input stream to good
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Your pet was not valid\n";
}
return 0;
}