// 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; inline constexpr struct dim_mass : base_dimension<"M"> { } dim_mass; inline constexpr struct dim_time : base_dimension<"T"> { } dim_time; inline constexpr struct dim_electric_current : base_dimension<"I"> { } dim_electric_current; // TODO Should the below use basic_symbol_text? How to name it for ASCII? inline constexpr struct dim_thermodynamic_temperature : base_dimension<"Θ"> { } dim_thermodynamic_temperature; inline constexpr struct dim_amount_of_substance : base_dimension<"N"> { } dim_amount_of_substance; inline constexpr struct dim_luminous_intensity : base_dimension<"J"> { } dim_luminous_intensity; // using dim_speed = decltype(dim_length / dim_time); // inline constexpr dim_speed dim_speed; // template // concept Length = QuantityOf; // 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 { inline constexpr struct dimensionless : system_reference { } dimensionless; } // namespace units namespace units::isq::si { inline constexpr struct length : system_reference { } length; inline constexpr struct time : system_reference { } time; // inline constexpr struct frequency : system_reference { inline constexpr struct frequency : system_reference { } frequency; // inline constexpr struct area : system_reference { inline constexpr struct area : system_reference { } area; // inline constexpr struct volume : system_reference { inline constexpr struct volume : system_reference { } volume; // inline constexpr struct speed : system_reference { inline constexpr struct speed : system_reference { } speed; // inline constexpr struct acceleration : system_reference { 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>>>); namespace si { // comparisons of equivalent dimensions static_assert(dim_length / dim_length == dim_one); static_assert(1 / dim_time == frequency::dimension); static_assert(1 / frequency::dimension == dim_time); static_assert(frequency::dimension * dim_time == dim_one); static_assert(dim_length * dim_length == area::dimension); static_assert(dim_length * dim_length != volume::dimension); static_assert(area::dimension / dim_length == dim_length); static_assert(dim_length * dim_length * dim_length == volume::dimension); static_assert(area::dimension * dim_length == volume::dimension); static_assert(volume::dimension / dim_length == area::dimension); static_assert(volume::dimension / dim_length / dim_length == dim_length); static_assert(area::dimension * area::dimension / dim_length == volume::dimension); static_assert(area::dimension * (area::dimension / dim_length) == volume::dimension); static_assert(volume::dimension / (dim_length * dim_length) == dim_length); static_assert(dim_length / dim_time == speed::dimension); static_assert(dim_length * dim_time != speed::dimension); static_assert(dim_length / dim_time / dim_time != speed::dimension); static_assert(dim_length / speed::dimension == dim_time); static_assert(speed::dimension * dim_time == dim_length); static_assert(dim_length / dim_time / dim_time == acceleration::dimension); static_assert(dim_length / (dim_time * dim_time) == acceleration::dimension); static_assert(speed::dimension / dim_time == acceleration::dimension); static_assert(speed::dimension / acceleration::dimension == dim_time); static_assert(acceleration::dimension * dim_time == speed::dimension); static_assert(acceleration::dimension * (dim_time * dim_time) == dim_length); static_assert(acceleration::dimension / speed::dimension == frequency::dimension); } // namespace si } // 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 == frequency::dimension); // static_assert(1 / frequency::dimension == second); // static_assert(frequency::dimension * second == one); // static_assert(metre * metre == area::dimension); // static_assert(metre * metre != volume::dimension); // static_assert(area::dimension / metre == metre); // static_assert(metre * metre * metre == volume::dimension); // static_assert(area::dimension * metre == volume::dimension); // static_assert(volume::dimension / metre == area::dimension); // static_assert(volume::dimension / metre / metre == metre); // static_assert(area::dimension * area::dimension / metre == volume::dimension); // static_assert(area::dimension * (area::dimension / metre) == volume::dimension); // static_assert(volume::dimension / (metre * metre) == metre); // static_assert(metre / second == speed::dimension); // static_assert(metre * second != speed::dimension); // static_assert(metre / second / second != speed::dimension); // static_assert(metre / speed::dimension == second); // static_assert(speed::dimension * second == metre); // static_assert(metre / second / second == acceleration::dimension); // static_assert(metre / (second * second) == acceleration::dimension); // static_assert(speed::dimension / second == acceleration::dimension); // static_assert(speed::dimension / acceleration::dimension == second); // static_assert(acceleration::dimension * second == speed::dimension); // static_assert(acceleration::dimension * (second * second) == metre); // static_assert(acceleration::dimension / speed::dimension == frequency::dimension); // 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 * isq::si::time[s]); quantity freq3(20); quantity freq4(20); quantity 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); template void print(); // constexpr auto avg_speed(quantity d, quantity t) { return d / t; } int main() { print(); // print(); print(); print(); print(); print(); print(); print(); print(); }