dimensions.cpp (4779B)
1 #include <iostream> 2 3 namespace system_of_units { 4 5 struct dimensions 6 { 7 static constexpr unsigned extent = 3; 8 int ds[extent] = {0,0,0}; 9 10 constexpr dimensions operator *(dimensions rhs) const 11 { 12 dimensions res; 13 for (unsigned i = 0; i < extent; ++i) 14 res.ds[i] = ds[i] + rhs.ds[i]; 15 return res; 16 } 17 constexpr dimensions operator /(dimensions rhs) const 18 { 19 dimensions res; 20 for (unsigned i = 0; i < extent; ++i) 21 res.ds[i] = ds[i] - rhs.ds[i]; 22 return res; 23 } 24 constexpr dimensions operator ()(int power) const 25 { 26 dimensions res; 27 for (unsigned i = 0; i < extent; ++i) 28 res.ds[i] = ds[i] * power; 29 return res; 30 } 31 }; 32 33 template <dimensions Us> 34 struct unit 35 { 36 long double v; 37 38 unit operator +(unit rhs) { return {v + rhs.v}; } 39 unit operator -(unit rhs) { return {v - rhs.v}; } 40 41 template <dimensions U2> 42 unit<Us*U2> operator *(unit<U2> rhs) { return {v * rhs.v}; } 43 template <dimensions U2> 44 unit<Us/U2> operator /(unit<U2> rhs) { return {v / rhs.v}; } 45 }; 46 47 constexpr dimensions second{1,0,0}; 48 constexpr dimensions meter{0,1,0}; 49 constexpr dimensions kilogram{0,0,1}; 50 51 using dimensionless = unit<dimensions{}>; 52 using time = unit<second>; 53 using length = unit<meter>; 54 using mass = unit<kilogram>; 55 using frequency = unit<second(-1)>; 56 using velocity = unit<meter/second>; 57 using acceleration = unit<meter/second(2)>; 58 using energy = unit<kilogram*meter(2)/second(2)>; 59 using power = unit<kilogram*meter(2)/second(3)>; 60 61 template <dimensions Us> 62 std::ostream& operator <<(std::ostream& out, unit<Us> u) 63 { 64 using U = decltype(u); 65 66 auto scale = abs(u.v); 67 68 if constexpr (std::is_same_v<U, dimensionless>) 69 { 70 if (scale < 2) 71 return out << u.v*100 << '%'; 72 else 73 return out << u.v; 74 } 75 if constexpr (std::is_same_v<U, time>) 76 { 77 if (scale < 1) 78 return out << u.v*1000 << "ms"; 79 else if (scale < 60) 80 return out << u.v << "s"; 81 else if (scale < 3600) 82 return out << u.v/60 << "min"; 83 else if (scale < 86400) 84 return out << u.v/3600 << "hour"; 85 else 86 return out << u.v/86400 << "days"; 87 } 88 if constexpr (std::is_same_v<U, mass>) 89 { 90 if (scale < 1) 91 return out << u.v << "g"; 92 else if (scale < 1000) 93 return out << u.v << "kg"; 94 else 95 return out << u.v/1000 << "t"; 96 } 97 98 if (scale < 1) 99 out << u.v*1000 << 'm'; 100 else if (scale < 1000) 101 out << u.v; 102 else if (scale < 1'000'000) 103 out << u.v/1000 << 'k'; 104 else 105 out << u.v/1'000'000 << 'M'; 106 107 if constexpr (std::is_same_v<U, length>) 108 return out << 'm'; 109 if constexpr (std::is_same_v<U, frequency>) 110 return out << "Hz"; 111 if constexpr (std::is_same_v<U, velocity>) 112 return out << "m/s"; 113 if constexpr (std::is_same_v<U, acceleration>) 114 return out << "m/s²"; 115 if constexpr (std::is_same_v<U, energy>) 116 return out << "J"; 117 if constexpr (std::is_same_v<U, power>) 118 return out << "W"; 119 120 out << '['; 121 for (auto d : Us.ds) 122 out << ' ' << d; 123 124 return out << " ]?"; 125 } 126 127 dimensionless operator ""_mu(long double v) { return {v}; } 128 time operator ""_s(long double v) { return {v}; } 129 time operator ""_min(long double v) { return {v*60}; } 130 time operator ""_hour(long double v) { return {v*3600}; } 131 length operator ""_m(long double v) { return {v}; } 132 length operator ""_km(long double v) { return {v*1000}; } 133 length operator ""_mile(long double v) { return {v*1609.344}; } 134 mass operator ""_kg(long double v) { return {v}; } 135 mass operator ""_t(long double v) { return {v * 1000}; } 136 frequency operator ""_Hz(long double v) { return {v}; } 137 frequency operator ""_kHz(long double v) { return {v*1000}; } 138 velocity operator ""_mps(long double v) { return {v}; } 139 velocity operator ""_kmph(long double v) { return {v/3.6}; } 140 velocity operator ""_mph(long double v) { return {v * 1609.344 / 3600}; } 141 acceleration operator ""_mpsps(long double v) { return {v}; } 142 energy operator ""_J(long double v) { return {v}; } 143 energy operator ""_kJ(long double v) { return {v*1000}; } 144 energy operator ""_MJ(long double v) { return {v*1'000'000}; } 145 power operator ""_W(long double v) { return {v}; } 146 power operator ""_kW(long double v) { return {v*1000}; } 147 148 } // namespace system_of_units 149 150 int main() 151 { 152 using namespace system_of_units; 153 using std::cout, std::endl; 154 155 cout << 1._mu << endl; 156 cout << 1._s << endl; 157 cout << 1._min << endl; 158 cout << 1._hour << endl; 159 cout << 1._m << endl; 160 cout << 1._km << endl; 161 cout << 1._mile << endl; 162 cout << 1._kg << endl; 163 cout << 1._t << endl; 164 cout << 1._Hz << endl; 165 cout << 1._kHz << endl; 166 cout << 1._mps << endl; 167 cout << 1._kmph << endl; 168 cout << 1._mph << endl; 169 cout << 1._mpsps << endl; 170 cout << 1._J << endl; 171 cout << 1._kJ << endl; 172 cout << 1._MJ << endl; 173 cout << 1._W << endl; 174 cout << 1._kW << endl; 175 cout << endl; 176 177 auto m = 5._m; 178 auto t = 2._s; 179 cout << m/t << endl; 180 cout << 3000._mph << endl; 181 cout << t/t << endl; 182 cout << 11.1_t << endl; 183 cout << 10._mpsps << endl; 184 }