Created
October 28, 2018 07:10
-
-
Save vmrob/514221d65a6f1bcf6c6a24d69e73354b to your computer and use it in GitHub Desktop.
Simple distance/velocity header
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Public domain, do whatever you want. | |
#include <chrono> | |
#include <cstdint> | |
class Distance { | |
public: | |
constexpr double kilometers() const { return _meters * 1e-3; } | |
constexpr double meters() const { return _meters; } | |
constexpr double decimeters() const { return _meters * 1e1; } | |
constexpr double centimeters() const { return _meters * 1e2; } | |
constexpr double millimeters() const { return _meters * 1e3; } | |
constexpr double micrometers() const { return _meters * 1e6; } | |
constexpr double nanometers() const { return _meters * 1e9; } | |
friend constexpr Distance Kilometers(double value); | |
friend constexpr Distance Meters(double value); | |
friend constexpr Distance Decimeters(double value); | |
friend constexpr Distance Centimeters(double value); | |
friend constexpr Distance Millimeters(double value); | |
friend constexpr Distance Micrometers(double value); | |
friend constexpr Distance Nanometers(double value); | |
friend constexpr Distance operator+(Distance lhs, Distance rhs); | |
friend constexpr Distance operator-(Distance lhs, Distance rhs); | |
friend constexpr Distance operator*(Distance lhs, double rhs); | |
friend constexpr Distance operator/(Distance lhs, double rhs); | |
constexpr Distance& operator+=(Distance lhs) { | |
_meters += lhs._meters; | |
return *this; | |
} | |
constexpr Distance& operator-=(Distance lhs) { | |
_meters -= lhs._meters; | |
return *this; | |
} | |
constexpr Distance& operator*=(double lhs) { | |
_meters *= lhs; | |
return *this; | |
} | |
constexpr Distance& operator/=(double lhs) { | |
_meters /= lhs; | |
return *this; | |
} | |
private: | |
double _meters = 0.0; | |
constexpr explicit Distance(double nm) : _meters{nm} {} | |
}; | |
constexpr Distance operator+(Distance lhs, Distance rhs) { | |
return Distance{lhs._meters + rhs._meters}; | |
} | |
constexpr Distance operator-(Distance lhs, Distance rhs) { | |
return Distance{lhs._meters - rhs._meters}; | |
} | |
constexpr Distance operator*(Distance lhs, double rhs) { | |
return Distance(lhs._meters * rhs); | |
} | |
constexpr Distance operator/(Distance lhs, double rhs) { | |
return Distance(lhs._meters / rhs); | |
} | |
#define DEFINE_DISTANCE_UNIT(func, magnitude, abbrev) \ | |
constexpr Distance func##s(double value) { \ | |
return Distance(value * magnitude); \ | |
} \ | |
\ | |
constexpr Distance operator""_##abbrev(long double value) { \ | |
return func##s(value); \ | |
} \ | |
\ | |
constexpr Distance operator""_##abbrev(unsigned long long int value) { \ | |
return func##s(value); \ | |
} | |
DEFINE_DISTANCE_UNIT(Kilometer, 1e3, km); | |
DEFINE_DISTANCE_UNIT(Meter, 1e0, m); | |
DEFINE_DISTANCE_UNIT(Decimeter, 1e-1, dm); | |
DEFINE_DISTANCE_UNIT(Centimeter, 1e-2, cm); | |
DEFINE_DISTANCE_UNIT(Millimeter, 1e-3, mm); | |
DEFINE_DISTANCE_UNIT(Micrometer, 1e-6, um); | |
DEFINE_DISTANCE_UNIT(Nanometer, 1e-9, nm); | |
#undef DEFINE_DISTANCE_UNIT | |
#define DEFINE_TIME_UNIT(func, num, den, abbrev) \ | |
constexpr std::chrono::duration<double, std::ratio<num, den>> func##s( \ | |
double value) { \ | |
return std::chrono::duration<double, std::ratio<num, den>>(value); \ | |
} \ | |
\ | |
constexpr std::chrono::duration<double, std::ratio<num, den>> \ | |
operator""_##abbrev(long double value) { \ | |
return func##s(value); \ | |
} \ | |
\ | |
constexpr std::chrono::duration<double, std::ratio<num, den>> \ | |
operator""_##abbrev(unsigned long long int value) { \ | |
return func##s(value); \ | |
} | |
DEFINE_TIME_UNIT(Hour, 3600, 1, h); | |
DEFINE_TIME_UNIT(Minute, 60, 1, min); | |
DEFINE_TIME_UNIT(Second, 1, 1, s); | |
DEFINE_TIME_UNIT(Millisecond, 1, 1000, ms); | |
DEFINE_TIME_UNIT(Microsecond, 1, 1'000'000, us); | |
DEFINE_TIME_UNIT(Nanosecond, 1, 1'000'000'000, ns); | |
#undef DEFINE_TIME_UNIT | |
class Velocity { | |
private: | |
public: | |
template <typename Rep, typename Period> | |
constexpr double metersPer(std::chrono::duration<Rep, Period> dur) const { | |
using Seconds = std::chrono::duration<double>; | |
return _distPerSecond.meters() | |
/ std::chrono::duration_cast<Seconds>(dur).count(); | |
} | |
template <typename Rep, typename Period> | |
constexpr double | |
kilometersPer(std::chrono::duration<Rep, Period> dur) const { | |
using Seconds = std::chrono::duration<double>; | |
return _distPerSecond.kilometers() | |
/ std::chrono::duration_cast<Seconds>(dur).count(); | |
} | |
friend constexpr Velocity operator+(Velocity lhs, Velocity rhs); | |
friend constexpr Velocity operator-(Velocity lhs, Velocity rhs); | |
friend constexpr Velocity operator*(Velocity lhs, double rhs); | |
friend constexpr Velocity operator/(Velocity lhs, double rhs); | |
constexpr Velocity& operator+=(Velocity rhs) { | |
_distPerSecond += rhs._distPerSecond; | |
return *this; | |
} | |
constexpr Velocity& operator-=(Velocity rhs) { | |
_distPerSecond -= rhs._distPerSecond; | |
return *this; | |
} | |
constexpr Velocity& operator*=(double rhs) { | |
_distPerSecond *= rhs; | |
return *this; | |
} | |
constexpr Velocity& operator/=(double rhs) { | |
_distPerSecond /= rhs; | |
return *this; | |
} | |
template <typename Rep, typename Period> | |
friend Velocity constexpr | |
operator/(Distance lhs, std::chrono::duration<Rep, Period> dur); | |
private: | |
Distance _distPerSecond; | |
constexpr explicit Velocity(Distance distancePerSecond) | |
: _distPerSecond{distancePerSecond} {} | |
}; | |
constexpr Velocity operator+(Velocity lhs, Velocity rhs) { | |
return Velocity{lhs._distPerSecond + rhs._distPerSecond}; | |
} | |
constexpr Velocity operator-(Velocity lhs, Velocity rhs) { | |
return Velocity{lhs._distPerSecond - rhs._distPerSecond}; | |
} | |
constexpr Velocity operator*(Velocity lhs, double rhs) { | |
return Velocity{lhs._distPerSecond * rhs}; | |
} | |
constexpr Velocity operator/(Velocity lhs, double rhs) { | |
return Velocity{lhs._distPerSecond / rhs}; | |
} | |
template <typename Rep, typename Period> | |
constexpr Velocity | |
operator/(Distance lhs, std::chrono::duration<Rep, Period> dur) { | |
using Seconds = std::chrono::duration<double>; | |
return Velocity{lhs / std::chrono::duration_cast<Seconds>(dur).count()}; | |
} | |
// a few tests | |
using namespace std::chrono_literals; | |
static_assert(Meters(1).nanometers() == 1'000'000'000); | |
static_assert(Kilometers(1).nanometers() == 1'000'000'000'000); | |
static_assert(Millimeters(50).micrometers() == 50'000); | |
static_assert(Seconds(50) == std::chrono::seconds(50)); | |
static_assert(Seconds(50) == 50_s); | |
static_assert(Milliseconds(50) == std::chrono::microseconds(50000)); | |
static_assert(50_us == std::chrono::microseconds(50)); | |
static_assert(50_us == 50us); | |
static_assert((Meters(1) / Seconds(1)).metersPer(Seconds(1)) == 1.0); | |
static_assert((1_m / 1_s).metersPer(1_s) == 1.0); | |
static_assert((Kilometers(1) / Seconds(1)).metersPer(Seconds(1)) == 1000.0); | |
static_assert((1_km / 1_s).metersPer(1_s) == 1000.0); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment