Overloading User-Defined Literals

Can user-defined literals be overloaded?

Yes, user-defined literals in C++ can be overloaded to handle different types of input. This allows you to create more versatile and expressive literals. Here's how you can do it:

Overloading Based on Parameter Type

You can overload user-defined literals by defining multiple functions with different parameter types. The C++ standard supports the following parameter types for literals:

  • unsigned long long for integers
  • long double for floating-point numbers
  • const char* for strings
  • char for characters

Here's an example of overloading user-defined literals for distance conversions:

#include <iostream>

class Distance {
 public:
  Distance(float value) : value{value} {}
  float value;
};

std::ostream& operator<<(
  std::ostream& os, Distance d) {
  os << d.value << " meters\n";
  return os;
}

Distance operator""_meters(long double val) {
  return Distance{static_cast<float>(val)};
}

Distance operator""_meters(unsigned long long val) {
  return Distance{static_cast<float>(val)};
}

Distance operator""_kilometers(long double val) {
  return Distance{static_cast<float>(val * 1000)};
}

Distance operator""_kilometers(unsigned long long val) {
  return Distance{static_cast<float>(val * 1000)};
}

int main() {
  Distance d1 = 3.0_kilometers;
  Distance d2 = 1500_meters;

  std::cout << d1;
  std::cout << d2;
}
3000 meters
1500 meters

Benefits of Overloading

  • Versatility: You can handle different input types with the same literal suffix.
  • Readability: Overloading literals makes your code more readable and expressive.

Example: Strings and Numbers

Here's another example demonstrating overloading with string and number literals:

#include <iostream>
#include <string>

std::string operator""_name(
  const char* str, size_t) {
  return std::string(str);
}

int operator""_age(unsigned long long val) {
  return static_cast<int>(val);
}

int main() {
  std::string playerName = "Legolas"_name;
  int playerAge = 2931_age;

  std::cout << "Player: " << playerName
    << ", Age: " << playerAge;
}
Player: Legolas, Age: 2931

Guidelines for Overloading

  • Consistent Naming: Use consistent and meaningful suffixes to avoid confusion.
  • Documentation: Clearly document the purpose of each overloaded version.
  • Testing: Test each overloaded function thoroughly to ensure they handle all expected input types correctly.

Conclusion

Overloading user-defined literals can enhance the expressiveness and versatility of your code. By following best practices and thoroughly testing your literals, you can create a powerful and intuitive API for your projects.

User Defined Literals

A practical guide to user-defined literals in C++, which allow us to write more descriptive and expressive values

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Custom Types and User-Defined Literals
Can user-defined literals be used with custom types?
Portability of User-Defined Literals
How can we ensure that our user-defined literals are portable across different compilers?
Underscore in User-Defined Literals
Why must user-defined literals start with an underscore?
Namespaces for User-Defined Literals
How do user-defined literals interact with namespaces?
Best Practices for User-Defined Literals
What are the best practices for using user-defined literals in large projects?
Negative Values in User-Defined Literals
How do we handle negative values in user-defined literals?
User-Defined Literals and Template Classes
How do user-defined literals work with template classes?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant