C++11 User Defined Literals for Representing Units of Time

February 25, 2014

C++11 allows you to specify user defined literals which finally gives the programmer the ability to define their own literals. For example, by default when you write 1.2F that means 1.2 float, and when you write 100ULL that means 100 unsigned long long. However, not only does this construct give you the ability to express different formats and suffixes, it also gives you the ability to manipulate what the actual value means.

This particular example is almost Ruby on Rails ActiveSupport like.

The following example always returns time in milliseconds, but allows the programmer to specify time values in units other than milliseconds. Surely this can be abused and there are way more powerful things you can do than what this example does. However, I think this is a very realistic example and makes the code cleaner and easier to read. No more putting (60 * 60 * 1000) type expressions scattered around the code. Did I mention less error prone?

#include <iostream>
 
using namespace std;
 
constexpr unsigned long long operator "" ms (unsigned long long n)
{
   // nothing to do
   return n;
}
 
constexpr unsigned long long operator "" sec (unsigned long long n)
{
   // convert seconds to milliseconds
   return n * 1000ULL;
}
 
constexpr unsigned long long operator "" min (unsigned long long n)
{
   // convert minutes to milliseconds
   return n * 60ULL * 1000ULL;
}
 
constexpr unsigned long long operator "" h (unsigned long long n)
{
   // convert hours to milliseconds
   return n * 60ULL * 60ULL * 1000ULL;
}
 
int main()
{
   cout << 20ms << endl;
   cout << 20sec << endl;
   cout << 20min << endl;
   cout << 20h << endl;
 
   cout << 1h + 5min + 3sec << endl;
 
   return 0;
}

The output of the above code.

$ ./literals 
20
20000
1200000
72000000
3903000

Related Posts

2 Comments

Comment March 1, 2014 by pyrtsa
Nice example. You should use the _ prefix for the literals, though (i.e. `20_ms`, not `20ms`), since the unprefixed literals are reserved for the compiler. And now that being less error prone is the goal, why not use standard duration types for the result type to not confuse them with plain integers? Here's an example, using C++1y return type deduction for avoiding further boilerplate: https://gist.github.com/pyrtsa/9288950
Comment March 1, 2014 by Rosario
I think that C++14 already did that. http://en.cppreference.com/w/cpp/chrono/operator%22%22h