// The MIT License (MIT) // // Copyright (c) 2018 Mateusz Pusz // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // #include #include namespace units::isq { inline constexpr struct dim_length : base_dimension<"L"> { } dim_length; // template // concept Length = QuantityOf; inline constexpr struct dim_time : base_dimension<"T"> { } dim_time; inline constexpr struct dim_frequency : decltype(1 / dim_time) { } dim_frequency; inline constexpr struct dim_area : decltype(dim_length * dim_length) { } dim_area; inline constexpr struct dim_volume : decltype(dim_area * dim_length) { } dim_volume; inline constexpr struct dim_speed : decltype(dim_length / dim_time) { } dim_speed; inline constexpr struct dim_acceleration : decltype(dim_speed / dim_time) { } dim_acceleration; // inline constexpr auto speed = length / time; } // namespace units::isq #include #include namespace units { namespace isq::si { // length units inline constexpr struct metre : named_unit<"m"> { } metre; inline constexpr struct kilometre : kilo { } kilometre; inline constexpr struct astronomical_unit : named_scaled_unit<"au", mag<149'597'870'700>(), metre> { } astronomical_unit; // area units inline constexpr struct square_metre : derived_unit { } square_metre; // volume units inline constexpr struct cubic_metre : derived_unit { } cubic_metre; // time units inline constexpr struct second : named_unit<"s"> { } second; inline constexpr struct minute : named_scaled_unit<"min", mag<60>(), second> { } minute; inline constexpr struct hour : named_scaled_unit<"h", mag<60>(), minute> { } hour; inline constexpr struct day : named_scaled_unit<"d", mag<24>(), hour> { } day; // not a time unit! inline constexpr struct second_squared : derived_unit { } second_squared; // mass units inline constexpr struct gram : named_unit<"g"> { } gram; inline constexpr struct kilogram : kilo { } kilogram; inline constexpr struct tonne : named_scaled_unit<"t", mag<1000>(), gram> { } tonne; // other units inline constexpr struct hertz : named_unit<"Hz", 1 / second> { } hertz; inline constexpr struct newton : named_unit<"N", kilogram * metre / second_squared> { } newton; inline constexpr struct pascal : named_unit<"Pa", kilogram / (metre * second_squared)> { } pascal; inline constexpr struct joule : named_unit<"J", newton * metre> { } joule; inline constexpr struct watt : named_unit<"W", joule / second> { } watt; namespace short_units { // TODO collide with reference names // inline namespace length { inline constexpr auto m = metre; inline constexpr auto km = kilometre; inline constexpr auto au = astronomical_unit; // } // namespace length // inline namespace area { inline constexpr auto m2 = square_metre; // } // inline namespace volume { inline constexpr auto m3 = cubic_metre; // } // inline namespace time { inline constexpr auto s = second; inline constexpr auto min = minute; inline constexpr auto h = hour; inline constexpr auto d = day; inline constexpr auto s2 = second_squared; // } // namespace time // inline namespace mass { inline constexpr auto g = gram; inline constexpr auto kg = kilogram; inline constexpr auto t = tonne; // } // namespace mass // inline namespace frequency { inline constexpr auto Hz = hertz; // } // inline namespace force { inline constexpr auto N = newton; // } // inline namespace pressure { inline constexpr auto Pa = pascal; // } // inline namespace energy { inline constexpr auto J = joule; // } // inline namespace power { inline constexpr auto W = watt; // } } // namespace short_units } // namespace isq::si } // namespace units #include namespace units::isq::si { inline constexpr struct length : system_reference { } length; inline constexpr struct time : system_reference { } time; inline constexpr struct frequency : system_reference { } frequency; inline constexpr struct area : system_reference { } area; inline constexpr struct volume : system_reference { } volume; inline constexpr struct speed : system_reference { } speed; inline constexpr struct acceleration : system_reference { } acceleration; } // namespace units::isq::si template inline constexpr bool is_of_type = std::is_same_v, T>; namespace units::isq { // derived dimension expression template syntax verification static_assert(is_of_type<1 / dim_time, derived_dimension>>); static_assert(is_of_type<1 / (1 / dim_time), struct dim_time>); static_assert(is_of_type); static_assert(is_of_type); static_assert(is_of_type>>); static_assert(is_of_type<1 / dim_time * dim_one, derived_dimension>>); static_assert(is_of_type>); static_assert(is_of_type>>); static_assert( is_of_type, struct dim_time>>); static_assert( is_of_type, struct dim_time>>); static_assert( is_of_type, struct dim_time>>); static_assert( is_of_type, struct dim_time>>); static_assert(is_of_type<1 / dim_time * dim_length, derived_dimension>>); static_assert(is_of_type<1 / dim_time * dim_time, struct dim_one>); static_assert(is_of_type); static_assert(is_of_type<1 / dim_time / dim_one, derived_dimension>>); static_assert(is_of_type); static_assert( is_of_type<1 / dim_time * (1 / dim_time), derived_dimension>>>); static_assert(is_of_type<1 / (dim_time * dim_time), derived_dimension>>>); static_assert(is_of_type<1 / (1 / (dim_time * dim_time)), derived_dimension>>); static_assert(is_of_type>>>); static_assert(is_of_type, per>>>); static_assert(is_of_type); static_assert( is_of_type>>); static_assert( is_of_type>>); static_assert(is_of_type, per>>); static_assert(is_of_type<1 / (dim_speed * dim_speed) * dim_length, derived_dimension>>>); // comparisons of equivalent dimensions static_assert(dim_length / dim_length == dim_one); static_assert(1 / dim_time == dim_frequency); static_assert(1 / dim_frequency == dim_time); static_assert(dim_frequency * dim_time == dim_one); static_assert(dim_length * dim_length == dim_area); static_assert(dim_length * dim_length != dim_volume); static_assert(dim_area / dim_length == dim_length); static_assert(dim_length * dim_length * dim_length == dim_volume); static_assert(dim_area * dim_length == dim_volume); static_assert(dim_volume / dim_length == dim_area); static_assert(dim_volume / dim_length / dim_length == dim_length); static_assert(dim_area * dim_area / dim_length == dim_volume); static_assert(dim_area * (dim_area / dim_length) == dim_volume); static_assert(dim_volume / (dim_length * dim_length) == dim_length); static_assert(dim_length / dim_time == dim_speed); static_assert(dim_length * dim_time != dim_speed); static_assert(dim_length / dim_time / dim_time != dim_speed); static_assert(dim_length / dim_speed == dim_time); static_assert(dim_speed * dim_time == dim_length); static_assert(dim_length / dim_time / dim_time == dim_acceleration); static_assert(dim_length / (dim_time * dim_time) == dim_acceleration); static_assert(dim_speed / dim_time == dim_acceleration); static_assert(dim_speed / dim_acceleration == dim_time); static_assert(dim_acceleration * dim_time == dim_speed); static_assert(dim_acceleration * (dim_time * dim_time) == dim_length); static_assert(dim_acceleration / dim_speed == dim_frequency); } // namespace units::isq namespace units::isq::si { // derived unit expression template syntax verification static_assert(is_of_type<1 / second, derived_unit>>); static_assert(is_of_type<1 / (1 / second), struct second>); static_assert(is_of_type); static_assert(is_of_type); static_assert(is_of_type>>); static_assert(is_of_type<1 / second * one, derived_unit>>); static_assert(is_of_type>); static_assert(is_of_type>>); static_assert(is_of_type, struct second>>); static_assert(is_of_type, struct second>>); static_assert(is_of_type, struct second>>); static_assert(is_of_type, struct second>>); static_assert(is_of_type<1 / second * metre, derived_unit>>); static_assert(is_of_type<1 / second * second, struct one>); static_assert(is_of_type); static_assert(is_of_type<1 / second / one, derived_unit>>); static_assert(is_of_type); static_assert(is_of_type<1 / second * (1 / second), derived_unit>>>); static_assert(is_of_type<1 / (second * second), derived_unit>>>); static_assert(is_of_type<1 / (1 / (second * second)), derived_unit>>); static_assert(is_of_type>>>); static_assert( is_of_type, per>>>); static_assert(is_of_type); static_assert(is_of_type>>); static_assert(is_of_type>>); // comparisons of equivalent dimensions // static_assert(metre / metre == one); // static_assert(1 / second == dim_frequency); // static_assert(1 / dim_frequency == second); // static_assert(dim_frequency * second == one); // static_assert(metre * metre == dim_area); // static_assert(metre * metre != dim_volume); // static_assert(dim_area / metre == metre); // static_assert(metre * metre * metre == dim_volume); // static_assert(dim_area * metre == dim_volume); // static_assert(dim_volume / metre == dim_area); // static_assert(dim_volume / metre / metre == metre); // static_assert(dim_area * dim_area / metre == dim_volume); // static_assert(dim_area * (dim_area / metre) == dim_volume); // static_assert(dim_volume / (metre * metre) == metre); // static_assert(metre / second == dim_speed); // static_assert(metre * second != dim_speed); // static_assert(metre / second / second != dim_speed); // static_assert(metre / dim_speed == second); // static_assert(dim_speed * second == metre); // static_assert(metre / second / second == dim_acceleration); // static_assert(metre / (second * second) == dim_acceleration); // static_assert(dim_speed / second == dim_acceleration); // static_assert(dim_speed / dim_acceleration == second); // static_assert(dim_acceleration * second == dim_speed); // static_assert(dim_acceleration * (second * second) == metre); // static_assert(dim_acceleration / dim_speed == dim_frequency); // Bq + Hz should not compile // Bq + Hz + 1/s should compile? } // namespace units::isq::si using namespace units; using namespace units::isq::si; using namespace units::isq::si::short_units; /* Frequency */ auto freq1 = 20 * frequency[Hz]; // /* Frequency */ auto freq2 = 20 / (1 * time[s]); quantity freq3(20); // quantity freq4(20); // quantity<1 / time[s]> freq5(20); /* Speed */ auto speed1 = 20 * speed[m / s]; /* Speed */ auto speed2 = 20 * (length[m] / isq::si::time[s]); // quantity speed3(20); // quantity speed4(20); // quantity / second> speed1(123); // quantity speed2(123); // auto speed3 = 123 * (kilo / second); // auto speed4 = 123 * (km / s); template void print(); // constexpr auto avg_speed(quantity d, quantity t) { return d / t; } int main() { print(); print(); }