Using std::chrono to make custom "SI unit" types std::chrono::duration is a great example of how to create "units" using std::ratio. std::ratio by itself is not very useful for a "units" library, and the two choices are either something like Boost.Unit (which can be very complicated to use) or to write it yourself (why reinvent the wheel?) Therefore I'm trying to write a wrapper around std::chrono::duration for some very basic types, like meter, feet, inches and centimeters.

Right now I feel like the way I've constructed the types is sloppy. It took me a while to get it right (at least for the test cases.) 

I also haven't figured out a good way to "rename" the types either. I've considered creating a templated struct that inherits from duration and then just renames the typedefs.

Another concern I have is whether I should use double instead of float and if there's a better way to avoid floating point errors.

#include &lt;iostream&gt;
#include &lt;chrono&gt;
#include &lt;ratio&gt;
#include &lt;cmath&gt;  /* for std::abs(double) */

// https://isocpp.org/wiki/faq/newbie#floating-point-arith
// "Why doesn’t my floating-point comparison work?"
constexpr inline bool isEqual(double x, double y)
{
  const double epsilon = 1e-5;
  return std::abs(x - y) &lt;= epsilon * std::abs(x);
  // see Knuth section 4.2.2 pages 217-218
}

int main()
{
    using meters = std::chrono::seconds;

    // There are 100 centimeters per meter
    using centimeters = std::chrono::duration&lt;float, std::ratio_divide&lt;meters::period, std::ratio&lt;100&gt;&gt;&gt;;

    // There are 2.54 centimeters per inch
    // and 39.3701 inches per meter
    using inches = std::chrono::duration&lt;float, std::ratio_divide&lt;centimeters::period, std::ratio&lt;100, 254&gt;&gt;&gt;;

    // There are 12 inches per foot
    using feet = std::chrono::duration&lt;float, std::ratio_multiply&lt;std::ratio&lt;12&gt;, inches::period&gt;&gt;;

    static_assert(inches(1) * 12 == feet(1), "");
    static_assert(centimeters(2.54) == inches(1), "");

    /* Thanks to rounding, inches(1) / 2.54 is 0.393701.
     * To get 0.3937007874, we need to use inches(1 / 2.54)
     * instead.
     */
    static_assert(inches(1 / 2.54) == centimeters(1), "");
    static_assert(centimeters(100) == meters(1), "");

    static_assert(inches(centimeters(100)) == meters(1), "");
    static_assert(isEqual(inches(centimeters(100)).count(), 39.3701), "");
}
Meters are Not Seconds

using meters = std::chrono::seconds;


I know it's obvious, but it bears stating. A meter is not a second. You compare a meter and a second, you cannot add them, etc. They are different types completely. So what you want is to make a different type:

template &lt;typename T, class Ratio = std::ratio&lt;1&gt;&gt;
class distance;

using meters = distance&lt;int64_t&gt;;


I'll leave the implementation of distance up to you. But it should absolutely be a different class than seconds!

Use the Standard Ratios

&lt;ratio&gt; actually provides a bunch of standard ratios for your use. You should use them:

using centimeters = distance&lt;int64_t, std::centi&gt;;


You'll note that std::centi is std::ratio&lt;1, 100&gt;, which makes more sense for centimeters than std::ratio&lt;100&gt;.

Use integral types

You'll notice I used int64_t instead of float or double. Prefer using integers whenever possible to simply sidestep the issue of floating point arithmetic altogether.