diff --git a/CMakeLists.txt b/CMakeLists.txt index f090756a..5dd89d06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,4 +43,4 @@ enable_testing() add_subdirectory(test) # add usage example -#add_subdirectory(example) +add_subdirectory(example) diff --git a/example/example.cpp b/example/example.cpp index 4f1e2e5e..2eb568b7 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -23,18 +23,21 @@ #include "units/si/velocity.h" #include +using namespace units; + +template +void foo(velocity v, time t) +{ + const auto distance = v * t; + + std::cout << "A car driving " << v.count() << " km/h in a time of " << t.count() << " minutes will pass " + << quantity_cast>(distance).count() << " meters.\n"; +} void foo() { - using namespace units; using namespace units::literals; - - const auto speed = 60_kmph; - const auto time = 10.0_min; - const auto distance = speed * time; - - std::cout << "A car driving " << speed.count() << " km/h in a time of " << time.count() << " minutes will pass " - << quantity_cast>(distance).count() << " meters.\n"; + foo(60_kmph, 10.0_min); } int main() diff --git a/src/include/units/bits/stdconcepts.h b/src/include/units/bits/stdconcepts.h index 9b73068e..12ff750e 100644 --- a/src/include/units/bits/stdconcepts.h +++ b/src/include/units/bits/stdconcepts.h @@ -27,18 +27,21 @@ namespace mp { - namespace detail { + namespace std_concepts { + + namespace detail { + template + concept bool SameHelper = std::is_same_v; + } + template - concept bool SameHelper = std::is_same_v; - } + concept bool Same = detail::SameHelper&& detail::SameHelper; - template - concept bool Same = detail::SameHelper && detail::SameHelper; - - template - concept bool ConvertibleTo = std::is_convertible_v && - requires(From (&f)()) { - static_cast(f()); - }; + template + concept bool ConvertibleTo = std::is_convertible_v&& requires(From (&f)()) + { + static_cast(f()); + }; + } // namespace std_concepts } // namespace mp diff --git a/src/include/units/bits/tools.h b/src/include/units/bits/tools.h index 713b7c4d..6660c1eb 100644 --- a/src/include/units/bits/tools.h +++ b/src/include/units/bits/tools.h @@ -26,7 +26,9 @@ #include #include -namespace mp { +namespace units { + + using namespace mp::std_concepts; // todo Remove when std::concepts will arrive // static_sign @@ -58,15 +60,15 @@ namespace mp { namespace detail { - template - struct is_ratio : std::false_type { - }; + template + struct is_ratio : std::false_type { + }; - template - struct is_ratio> : std::true_type { - }; + template + struct is_ratio> : std::true_type { + }; - } + } // namespace detail template concept bool Ratio = detail::is_ratio::value; @@ -84,4 +86,4 @@ namespace mp { template using common_ratio_t = typename common_ratio::type; -} // namespace mp +} // namespace units diff --git a/src/include/units/bits/type_list.h b/src/include/units/bits/type_list.h index 5a83e4df..865d06d2 100644 --- a/src/include/units/bits/type_list.h +++ b/src/include/units/bits/type_list.h @@ -30,12 +30,14 @@ namespace mp { namespace detail { template - struct is_type_list : std::false_type {}; + struct is_type_list : std::false_type { + }; template typename T, typename... Types> - struct is_type_list> : std::true_type {}; + struct is_type_list> : std::true_type { + }; - } + } // namespace detail template concept bool TypeList = detail::is_type_list::value; @@ -84,8 +86,8 @@ namespace mp { using base = split_impl; using base_first = typename base::first_list; using base_second = typename base::second_list; - using first_list = std::conditional_t, base_first>; - using second_list = std::conditional_t>; + using first_list = std::conditional_t < Idx, base_first>; + using second_list = std::conditional_t < Idx>; }; } // namespace detail @@ -133,10 +135,8 @@ namespace mp { struct type_list_merge_sorted, List, Pred> { using type = std::conditional_t< Pred::value, - type_list_push_front_t, List, Pred>, - Lhs1>, - type_list_push_front_t, List, Pred>, - Rhs1>>; + type_list_push_front_t, List, Pred>, Lhs1>, + type_list_push_front_t, List, Pred>, Rhs1>>; }; // sort diff --git a/src/include/units/dimension.h b/src/include/units/dimension.h index 9524dc94..4836b181 100644 --- a/src/include/units/dimension.h +++ b/src/include/units/dimension.h @@ -35,12 +35,13 @@ namespace units { // dim_id_less template - struct dim_id_less : std::bool_constant { + struct dim_id_less : std::bool_constant < D1::value { }; // exp - template + template // todo: to be replaced with fixed_string when supported by the compilers + // template struct exp { using dimension = BaseDimension; static constexpr int value = Value; @@ -55,12 +56,11 @@ namespace units { template struct is_exp> : std::true_type { }; - } + } // namespace detail template concept bool Exponent = detail::is_exp::value; - // exp_less template @@ -88,16 +88,17 @@ namespace units { // is_dimension namespace detail { template - struct is_dimension : std::false_type {}; + struct is_dimension : std::false_type { + }; template - struct is_dimension> : std::bool_constant<(is_exp::value && ...)> {}; - } + struct is_dimension> : std::bool_constant<(is_exp::value && ...)> { + }; + } // namespace detail template concept bool Dimension = detail::is_dimension::value; - // make_dimension namespace detail { @@ -121,8 +122,8 @@ namespace units { template struct dim_consolidate> { using rest = dim_consolidate_t>; - using type = std::conditional_t>, dimension, - mp::type_list_push_front_t>; + using type = + std::conditional_t>, dimension, mp::type_list_push_front_t>; }; template @@ -141,8 +142,6 @@ namespace units { template using make_dimension_t = typename make_dimension::type; - - // dimension_multiply template diff --git a/src/include/units/quantity.h b/src/include/units/quantity.h index 1821b2d3..9fb4dff7 100644 --- a/src/include/units/quantity.h +++ b/src/include/units/quantity.h @@ -22,16 +22,15 @@ #pragma once -#include "bits/tools.h" -#include "dimension.h" +#include "unit.h" #include namespace units { // is_quantity - template - class quantity; + template + requires Same class quantity; namespace detail { @@ -39,11 +38,11 @@ namespace units { struct is_quantity : std::false_type { }; - template - struct is_quantity> : std::true_type { + template + struct is_quantity> : std::true_type { }; - } + } // namespace detail template concept bool Quantity = detail::is_quantity::value; @@ -51,7 +50,8 @@ namespace units { // treat_as_floating_point template - struct treat_as_floating_point : std::is_floating_point {}; + struct treat_as_floating_point : std::is_floating_point { + }; template inline constexpr bool treat_as_floating_point_v = treat_as_floating_point::value; @@ -60,38 +60,38 @@ namespace units { namespace detail { - template + template struct quantity_cast_impl { - template - static constexpr To cast(const quantity& q) + template + static constexpr To cast(const quantity, Rep>& q) { return To(static_cast(static_cast(q.count()) * static_cast(CR::num) / static_cast(CR::den))); } }; - template + template struct quantity_cast_impl { - template - static constexpr To cast(const quantity& q) + template + static constexpr To cast(const quantity, Rep>& q) { return To(static_cast(q.count())); } }; - template + template struct quantity_cast_impl { - template - static constexpr To cast(const quantity& q) + template + static constexpr To cast(const quantity, Rep>& q) { return To(static_cast(static_cast(q.count()) / static_cast(CR::den))); } }; - template + template struct quantity_cast_impl { - template - static constexpr To cast(const quantity& q) + template + static constexpr To cast(const quantity, Rep>& q) { return To(static_cast(static_cast(q.count()) * static_cast(CR::num))); } @@ -99,11 +99,10 @@ namespace units { } // namespace detail - template - requires mp::Same - constexpr To quantity_cast(const quantity& q) + template + requires Same constexpr To quantity_cast(const quantity& q) { - using c_ratio = std::ratio_divide; + using c_ratio = std::ratio_divide; using c_rep = std::common_type_t; using cast = detail::quantity_cast_impl; return cast::cast(q); @@ -120,30 +119,33 @@ namespace units { // quantity - template> - class quantity { + template + requires Same class quantity { Rep value_; + public: using dimension = D; + using unit = U; using rep = Rep; - using ratio = R; static_assert(!detail::is_quantity::value, "rep cannot be a quantity"); - static_assert(ratio::num > 0, "ratio must be positive"); quantity() = default; quantity(const quantity&) = default; template - requires mp::ConvertibleTo && (treat_as_floating_point_v || !treat_as_floating_point_v) - constexpr explicit quantity(const Rep2& r) : value_{static_cast(r)} + requires ConvertibleTo && + (treat_as_floating_point_v || !treat_as_floating_point_v)constexpr explicit quantity(const Rep2& r) + : value_{static_cast(r)} { } - template - requires mp::ConvertibleTo && (treat_as_floating_point_v || - (std::ratio_divide::den == 1 && !treat_as_floating_point_v)) - constexpr quantity(const quantity& q) : value_{quantity_cast(q).count()} + template + requires Same&& ConvertibleTo && + (treat_as_floating_point_v || + (std::ratio_divide::den == 1 && + !treat_as_floating_point_v)) constexpr quantity(const Q2& q) + : value_{quantity_cast(q).count()} { } @@ -210,149 +212,146 @@ namespace units { }; // clang-format off - template - std::common_type_t, quantity> - constexpr operator+(const quantity& lhs, - const quantity& rhs) + template + std::common_type_t, quantity> + constexpr operator+(const quantity& lhs, + const quantity& rhs) { - using ret = std::common_type_t, quantity>; + using ret = std::common_type_t, quantity>; return ret(ret(lhs).count() + ret(rhs).count()); } - template - std::common_type_t, quantity> - constexpr operator-(const quantity& lhs, - const quantity& rhs) + template + std::common_type_t, quantity> + constexpr operator-(const quantity& lhs, + const quantity& rhs) { - using ret = std::common_type_t, quantity>; + using ret = std::common_type_t, quantity>; return ret(ret(lhs).count() - ret(rhs).count()); } - template - quantity, R> - constexpr operator*(const quantity& q, + template + quantity> + constexpr operator*(const quantity& q, const Rep2& v) { - using ret = quantity, R>; + using ret = quantity>; return ret(ret(q).count() * v); } - template - quantity, R> + template + quantity> constexpr operator*(const Rep1& v, - const quantity& q) + const quantity& q) { return q * v; } - template - requires treat_as_floating_point_v> || std::ratio_multiply::den == 1 - quantity, std::common_type_t, std::ratio_multiply> - constexpr operator*(const quantity& lhs, - const quantity& rhs) + template + requires treat_as_floating_point_v> || std::ratio_multiply::den == 1 + quantity, unit, std::ratio_multiply>, std::common_type_t> + constexpr operator*(const quantity& lhs, + const quantity& rhs) { - using ret = quantity, std::common_type_t, std::ratio_multiply>; + using dim = dimension_multiply_t; + using ret = quantity>, std::common_type_t>; return ret(lhs.count() * rhs.count()); } - template - quantity>, std::common_type_t, R> + template + quantity...>, unit...>, std::ratio>, std::common_type_t> constexpr operator/(const Rep1& v, - const quantity, Rep2, R>& q) + const quantity, U, Rep2>& q) { - using ret = quantity>, std::common_type_t, R>; - using den = quantity, std::common_type_t, R>; + using dim = dimension...>; + using ret = quantity>, std::common_type_t>; + using den = quantity, U, std::common_type_t>; return ret(v / den(q).count()); } - template - quantity, R> - constexpr operator/(const quantity& q, + template + quantity> + constexpr operator/(const quantity& q, const Rep2& v) { - using ret = quantity, R>; + using ret = quantity>; return ret(ret(q).count() / v); } - template + template std::common_type_t - constexpr operator/(const quantity& lhs, - const quantity& rhs) + constexpr operator/(const quantity& lhs, + const quantity& rhs) { - using cq = std::common_type_t, quantity>; + using cq = std::common_type_t, quantity>; return cq(lhs).count() / cq(rhs).count(); } - template - requires treat_as_floating_point_v> || std::ratio_divide::den == 1 - quantity, std::common_type_t, std::ratio_divide> - constexpr operator/(const quantity& lhs, - const quantity& rhs) + template + requires treat_as_floating_point_v> || std::ratio_divide::den == 1 + quantity, unit, std::ratio_divide>, std::common_type_t> + constexpr operator/(const quantity& lhs, + const quantity& rhs) { - using ret = quantity, std::common_type_t, std::ratio_divide>; + using dim = dimension_divide_t; + using ret = quantity>, std::common_type_t>; return ret(lhs.count() / rhs.count()); } - template - quantity, R> - constexpr operator%(const quantity& q, + template + quantity> + constexpr operator%(const quantity& q, const Rep2& v) { - using ret = quantity, R>; + using ret = quantity>; return ret(ret(q).count() % v); } - template - std::common_type_t, quantity> - constexpr operator%(const quantity& lhs, - const quantity& rhs) + template + std::common_type_t, quantity> + constexpr operator%(const quantity& lhs, + const quantity& rhs) { - using ret = std::common_type_t, quantity>; + using ret = std::common_type_t, quantity>; return ret(ret(lhs).count() % ret(rhs).count()); } // clang-format on - template - constexpr bool operator==(const quantity& lhs, - const quantity& rhs) + template + constexpr bool operator==(const quantity& lhs, const quantity& rhs) { - using ct = std::common_type_t, quantity>; + using ct = std::common_type_t, quantity>; return ct(lhs).count() == ct(rhs).count(); } - template - constexpr bool operator!=(const quantity& lhs, - const quantity& rhs) + template + constexpr bool operator!=(const quantity& lhs, const quantity& rhs) { return !(lhs == rhs); } - template - constexpr bool operator<(const quantity& lhs, - const quantity& rhs) + template + constexpr bool operator<(const quantity& lhs, const quantity& rhs) { - using ct = std::common_type_t, quantity>; + using ct = std::common_type_t, quantity>; return ct(lhs).count() < ct(rhs).count(); } - template - constexpr bool operator<=(const quantity& lhs, - const quantity& rhs) + template + constexpr bool operator<=(const quantity& lhs, const quantity& rhs) { return !(rhs < lhs); } - template - constexpr bool operator>(const quantity& lhs, - const quantity& rhs) + template + constexpr bool operator>(const quantity& lhs, const quantity& rhs) { return rhs < lhs; } - template - constexpr bool operator>=(const quantity& lhs, - const quantity& rhs) + template + constexpr bool operator>=(const quantity& lhs, const quantity& rhs) { return !(lhs < rhs); } @@ -362,10 +361,10 @@ namespace units { namespace std { // todo: simplified - template - struct common_type, units::quantity> { - using type = - units::quantity, mp::common_ratio_t>; + template + struct common_type, units::quantity> { + using type = units::quantity>, + std::common_type_t>; }; } // namespace std diff --git a/src/include/units/si/base_dimensions.h b/src/include/units/si/base_dimensions.h index 6b22f5e5..b939e86a 100644 --- a/src/include/units/si/base_dimensions.h +++ b/src/include/units/si/base_dimensions.h @@ -26,6 +26,8 @@ namespace units { + // todo: to be replaced with fixed_string when supported by the compilers + struct base_dim_length : dim_id<0> {}; struct base_dim_mass : dim_id<1> {}; struct base_dim_time : dim_id<2> {}; diff --git a/src/include/units/si/frequency.h b/src/include/units/si/frequency.h index 0d9bb42b..ac7731fc 100644 --- a/src/include/units/si/frequency.h +++ b/src/include/units/si/frequency.h @@ -29,54 +29,43 @@ namespace units { using dimension_frequency = make_dimension_t>; - template> - using frequency = quantity; + using millihertz = unit; + using hertz = unit>; + using kilohertz = unit; + using megahertz = unit; + using gigahertz = unit; + using terahertz = unit; - template - using millihertzs = frequency; - - template - using hertzs = frequency; - - template - using kilohertzs = frequency; - - template - using megahertzs = frequency; - - template - using gigahertzs = frequency; - - template - using terahertzs = frequency; + template + using frequency = quantity; // ... namespace literals { // mHz - constexpr auto operator""_mHz(unsigned long long l) { return millihertzs(l); } - constexpr auto operator""_mHz(long double l) { return millihertzs(l); } + constexpr auto operator""_mHz(unsigned long long l) { return frequency(l); } + constexpr auto operator""_mHz(long double l) { return frequency(l); } // Hz - constexpr auto operator""_Hz(unsigned long long l) { return hertzs(l); } - constexpr auto operator""_Hz(long double l) { return hertzs(l); } + constexpr auto operator""_Hz(unsigned long long l) { return frequency(l); } + constexpr auto operator""_Hz(long double l) { return frequency(l); } // kHz - constexpr auto operator""_kHz(unsigned long long l) { return kilohertzs(l); } - constexpr auto operator""_kHz(long double l) { return kilohertzs(l); } + constexpr auto operator""_kHz(unsigned long long l) { return frequency(l); } + constexpr auto operator""_kHz(long double l) { return frequency(l); } // MHz - constexpr auto operator""_MHz(unsigned long long l) { return megahertzs(l); } - constexpr auto operator""_MHz(long double l) { return megahertzs(l); } + constexpr auto operator""_MHz(unsigned long long l) { return frequency(l); } + constexpr auto operator""_MHz(long double l) { return frequency(l); } // GHz - constexpr auto operator""_GHz(unsigned long long l) { return gigahertzs(l); } - constexpr auto operator""_GHz(long double l) { return gigahertzs(l); } + constexpr auto operator""_GHz(unsigned long long l) { return frequency(l); } + constexpr auto operator""_GHz(long double l) { return frequency(l); } // THz - constexpr auto operator""_THz(unsigned long long l) { return terahertzs(l); } - constexpr auto operator""_THz(long double l) { return terahertzs(l); } + constexpr auto operator""_THz(unsigned long long l) { return frequency(l); } + constexpr auto operator""_THz(long double l) { return frequency(l); } } // namespace literals diff --git a/src/include/units/si/length.h b/src/include/units/si/length.h index 58a0a892..150330df 100644 --- a/src/include/units/si/length.h +++ b/src/include/units/si/length.h @@ -29,33 +29,26 @@ namespace units { using dimension_length = make_dimension_t>; - template> - using length = quantity; + using millimeter = unit; + using meter = unit>; + using kilometer = unit; - template - using millimeters = length; - - template - using meters = length; - - template - using kilometers = length; - - // ... + template + using length = quantity; namespace literals { // mm - constexpr auto operator""_mm(unsigned long long l) { return millimeters(l); } - constexpr auto operator""_mm(long double l) { return millimeters(l); } + constexpr auto operator""_mm(unsigned long long l) { return length(l); } + constexpr auto operator""_mm(long double l) { return length(l); } // m - constexpr auto operator""_m(unsigned long long l) { return meters(l); } - constexpr auto operator""_m(long double l) { return meters(l); } + constexpr auto operator""_m(unsigned long long l) { return length(l); } + constexpr auto operator""_m(long double l) { return length(l); } // km - constexpr auto operator""_km(unsigned long long l) { return kilometers(l); } - constexpr auto operator""_km(long double l) { return kilometers(l); } + constexpr auto operator""_km(unsigned long long l) { return length(l); } + constexpr auto operator""_km(long double l) { return length(l); } } // namespace literals diff --git a/src/include/units/si/time.h b/src/include/units/si/time.h index f1255623..d32c0160 100644 --- a/src/include/units/si/time.h +++ b/src/include/units/si/time.h @@ -29,54 +29,43 @@ namespace units { using dimension_time = make_dimension_t>; - template> - using time = quantity; + using nanosecond = unit; + using microsecond = unit; + using millisecond = unit; + using second = unit>; + using minute = unit>; + using hour = unit>; - template - using nanoseconds = time; - - template - using microseconds = time; - - template - using milliseconds = time; - - template - using seconds = time; - - template - using minutes = time>; - - template - using hours = time>; + template + using time = quantity; // ... namespace literals { // ns - constexpr auto operator""_ns(unsigned long long l) { return nanoseconds(l); } - constexpr auto operator""_ns(long double l) { return nanoseconds(l); } + constexpr auto operator""_ns(unsigned long long l) { return time(l); } + constexpr auto operator""_ns(long double l) { return time(l); } // us - constexpr auto operator""_us(unsigned long long l) { return microseconds(l); } - constexpr auto operator""_us(long double l) { return microseconds(l); } + constexpr auto operator""_us(unsigned long long l) { return time(l); } + constexpr auto operator""_us(long double l) { return time(l); } // ms - constexpr auto operator""_ms(unsigned long long l) { return milliseconds(l); } - constexpr auto operator""_ms(long double l) { return milliseconds(l); } + constexpr auto operator""_ms(unsigned long long l) { return time(l); } + constexpr auto operator""_ms(long double l) { return time(l); } // s - constexpr auto operator""_s(unsigned long long l) { return seconds(l); } - constexpr auto operator""_s(long double l) { return seconds(l); } + constexpr auto operator""_s(unsigned long long l) { return time(l); } + constexpr auto operator""_s(long double l) { return time(l); } // min - constexpr auto operator""_min(unsigned long long l) { return minutes(l); } - constexpr auto operator""_min(long double l) { return minutes(l); } + constexpr auto operator""_min(unsigned long long l) { return time(l); } + constexpr auto operator""_min(long double l) { return time(l); } // h - constexpr auto operator""_h(unsigned long long l) { return hours(l); } - constexpr auto operator""_h(long double l) { return hours(l); } + constexpr auto operator""_h(unsigned long long l) { return time(l); } + constexpr auto operator""_h(long double l) { return time(l); } } // namespace literals diff --git a/src/include/units/si/velocity.h b/src/include/units/si/velocity.h index 069c803a..6b6b917e 100644 --- a/src/include/units/si/velocity.h +++ b/src/include/units/si/velocity.h @@ -30,33 +30,28 @@ namespace units { using dimension_velocity = make_dimension_t, exp>; - template> - using velocity = quantity; + using meter_per_second = unit>; + using kilometer_per_hour = unit>; + using mile_per_hour = unit>; - template - using meters_per_second = velocity; - - template - using kilometers_per_hour = velocity>; - - template - using miles_per_hour = velocity>; + template + using velocity = quantity; // ... namespace literals { // mps - constexpr auto operator""_mps(unsigned long long l) { return meters_per_second(l); } - constexpr auto operator""_mps(long double l) { return meters_per_second(l); } + constexpr auto operator""_mps(unsigned long long l) { return velocity(l); } + constexpr auto operator""_mps(long double l) { return velocity(l); } // kmph - constexpr auto operator""_kmph(unsigned long long l) { return kilometers_per_hour(l); } - constexpr auto operator""_kmph(long double l) { return kilometers_per_hour(l); } + constexpr auto operator""_kmph(unsigned long long l) { return velocity(l); } + constexpr auto operator""_kmph(long double l) { return velocity(l); } // mph - constexpr auto operator""_mph(unsigned long long l) { return miles_per_hour(l); } - constexpr auto operator""_mph(long double l) { return miles_per_hour(l); } + constexpr auto operator""_mph(unsigned long long l) { return velocity(l); } + constexpr auto operator""_mph(long double l) { return velocity(l); } } // namespace literals diff --git a/src/include/units/unit.h b/src/include/units/unit.h new file mode 100644 index 00000000..3ac885fa --- /dev/null +++ b/src/include/units/unit.h @@ -0,0 +1,62 @@ +// 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. + +#pragma once + +#include "bits/tools.h" +#include "dimension.h" + +namespace units { + + template + struct unit { + using dimension = D; + using ratio = R; + static_assert(ratio::num > 0, "ratio must be positive"); + }; + + // is_unit + + namespace detail { + + template + struct is_unit : std::false_type { + }; + + template + struct is_unit> : std::true_type { + }; + + } + + template + concept bool Unit = detail::is_unit::value; + +// template +// auto operator/(U1, U2) +// { +// return ; +// } +// +// unit, std::ratio_divide> + +} // namespace units diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 112dc8b5..47a22405 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -31,7 +31,6 @@ include(tools) # add dependencies enable_testing() -find_package(GTest MODULE REQUIRED) if(NOT TARGET mp::units) find_package(units CONFIG REQUIRED) endif() diff --git a/test/test_quantity.cpp b/test/test_quantity.cpp index 801b7172..73e329c6 100644 --- a/test/test_quantity.cpp +++ b/test/test_quantity.cpp @@ -74,102 +74,103 @@ namespace { // class invariants - // constexpr quantity> error(0_m); // should trigger a static_assert - // constexpr quantity error(0); // should trigger a static_assert - // constexpr quantity> error(0); // should trigger a static_assert + // constexpr quantity q; // should a static_assert + // constexpr quantity> error(0_m); // should trigger a static_assert + // constexpr quantity error(0); // should trigger a static_assert + // constexpr quantity> error(0); // should trigger a static_assert // member types - static_assert(std::is_same_v::rep, int>); - static_assert(std::is_same_v::rep, float>); - static_assert(std::is_same_v::ratio, std::ratio<1, 1>>); - static_assert(std::is_same_v::ratio, std::ratio<1000, 1>>); + static_assert(std::is_same_v::rep, int>); + static_assert(std::is_same_v::rep, float>); + static_assert(std::is_same_v::unit, meter>); + static_assert(std::is_same_v::unit, kilometer>); // constructors - static_assert(meters().count() == 0); - constexpr meters kilometer{1000}; - static_assert(kilometer.count() == 1000); - static_assert(meters(kilometer).count() == kilometer.count()); + static_assert(length().count() == 0); + constexpr length km{1000}; + static_assert(km.count() == 1000); + static_assert(length(km).count() == km.count()); - static_assert(meters(1).count() == 1); - static_assert(meters(my_value(1)).count() == 1); - static_assert(meters>(1).count() == 1); - // static_assert(meters(1.0).count() == 1); // should not compile - // static_assert(meters(my_value(1.0)).count() == 1); // should not compile - // static_assert(meters>(1.0).count() == 1); // should not compile - static_assert(meters(1.0).count() == 1.0); - static_assert(meters(my_value(1.0)).count() == 1.0); - static_assert(meters(1).count() == 1.0); - static_assert(meters(my_value(1)).count() == 1.0); - static_assert(meters(3.14f).count() == 3.14f); - static_assert(meters>(1.0).count() == 1.0); - static_assert(meters>(1).count() == 1.0); - static_assert(meters>(3.14f).count() == 3.14f); + static_assert(length(1).count() == 1); + static_assert(length(my_value(1)).count() == 1); + static_assert(length>(1).count() == 1); + // static_assert(length(1.0).count() == 1); // should not compile + // static_assert(length(my_value(1.0)).count() == 1); // should not compile + // static_assert(length>(1.0).count() == 1); // should not compile + static_assert(length(1.0).count() == 1.0); + static_assert(length(my_value(1.0)).count() == 1.0); + static_assert(length(1).count() == 1.0); + static_assert(length(my_value(1)).count() == 1.0); + static_assert(length(3.14f).count() == 3.14f); + static_assert(length>(1.0).count() == 1.0); + static_assert(length>(1).count() == 1.0); + static_assert(length>(3.14f).count() == 3.14f); - static_assert(meters(kilometer).count() == 1000); - // static_assert(meters(meters(3.14)).count() == 3); // should not compile - static_assert(meters(quantity_cast>(3.14_m)).count() == 3); - // static_assert(meters(meters>(1000.0)).count() == 1000); // should not compile - // static_assert(meters>(1000.0_m).count() == 1000); // should not compile - static_assert(meters(1000.0_m).count() == 1000.0); - static_assert(meters(meters>(1000.0)).count() == 1000.0); - static_assert(meters>(1000.0_m).count() == 1000.0); - static_assert(meters(kilometer).count() == 1000.0); - static_assert(meters>(kilometer).count() == 1000.0); - static_assert(meters(1_km).count() == 1000); - // static_assert(meters(1_s).count() == 1); // should not compile - // static_assert(kilometers(1010_m).count() == 1); // should not compile - static_assert(kilometers(quantity_cast>(1010_m)).count() == 1); + static_assert(length(km).count() == 1000); + // static_assert(length(length(3.14)).count() == 3); // should not compile + static_assert(length(quantity_cast>(3.14_m)).count() == 3); + // static_assert(length(length>(1000.0)).count() == 1000); // should not compile + // static_assert(length>(1000.0_m).count() == 1000); // should not compile + static_assert(length(1000.0_m).count() == 1000.0); + static_assert(length(length>(1000.0)).count() == 1000.0); + static_assert(length>(1000.0_m).count() == 1000.0); + static_assert(length(km).count() == 1000.0); + static_assert(length>(km).count() == 1000.0); + static_assert(length(1_km).count() == 1000); + // static_assert(length(1_s).count() == 1); // should not compile + // static_assert(length(1010_m).count() == 1); // should not compile + static_assert(length(quantity_cast>(1010_m)).count() == 1); // assignment operator static_assert([]() { - meters l1(1), l2(2); + length l1(1), l2(2); return l2 = l1; }() .count() == 1); // static member functions - static_assert(meters::zero().count() == 0); - static_assert(meters::min().count() == std::numeric_limits::lowest()); - static_assert(meters::max().count() == std::numeric_limits::max()); - static_assert(meters::zero().count() == 0.0); - static_assert(meters::min().count() == std::numeric_limits::lowest()); - static_assert(meters::max().count() == std::numeric_limits::max()); - static_assert(meters>::zero().count() == 0); - static_assert(meters>::min().count() == std::numeric_limits::lowest()); - static_assert(meters>::max().count() == std::numeric_limits::max()); - static_assert(meters>::zero().count() == 0.0); - static_assert(meters>::min().count() == std::numeric_limits::lowest()); - static_assert(meters>::max().count() == std::numeric_limits::max()); + static_assert(length::zero().count() == 0); + static_assert(length::min().count() == std::numeric_limits::lowest()); + static_assert(length::max().count() == std::numeric_limits::max()); + static_assert(length::zero().count() == 0.0); + static_assert(length::min().count() == std::numeric_limits::lowest()); + static_assert(length::max().count() == std::numeric_limits::max()); + static_assert(length>::zero().count() == 0); + static_assert(length>::min().count() == std::numeric_limits::lowest()); + static_assert(length>::max().count() == std::numeric_limits::max()); + static_assert(length>::zero().count() == 0.0); + static_assert(length>::min().count() == std::numeric_limits::lowest()); + static_assert(length>::max().count() == std::numeric_limits::max()); // unary member operators - static_assert((+kilometer).count() == 1000); - static_assert((-kilometer).count() == -1000); - static_assert((+(-kilometer)).count() == -1000); - static_assert((-(-kilometer)).count() == 1000); + static_assert((+km).count() == 1000); + static_assert((-km).count() == -1000); + static_assert((+(-km)).count() == -1000); + static_assert((-(-km)).count() == 1000); // binary member operators static_assert([](auto v) { auto vv = v++; return std::make_pair(v, vv); - }(kilometer) == std::make_pair(meters(1001), meters(1000))); + }(km) == std::make_pair(length(1001), length(1000))); static_assert([](auto v) { auto vv = ++v; return std::make_pair(v, vv); - }(kilometer) == std::make_pair(meters(1001), meters(1001))); + }(km) == std::make_pair(length(1001), length(1001))); static_assert([](auto v) { auto vv = v--; return std::make_pair(v, vv); - }(kilometer) == std::make_pair(meters(999), meters(1000))); + }(km) == std::make_pair(length(999), length(1000))); static_assert([](auto v) { auto vv = --v; return std::make_pair(v, vv); - }(kilometer) == std::make_pair(meters(999), meters(999))); + }(km) == std::make_pair(length(999), length(999))); // compound assignment @@ -182,18 +183,18 @@ namespace { // non-member arithmetic operators - static_assert(std::is_same_v() + meters()), meters>); - static_assert(std::is_same_v() - meters()), meters>); - static_assert(std::is_same_v() * 1.0f), meters>); - static_assert(std::is_same_v()), meters>); - static_assert(std::is_same_v() / 1.0f), meters>); - static_assert(std::is_same_v() / meters()), float>); - static_assert(std::is_same_v() % short(1)), meters>); - static_assert(std::is_same_v() % meters(1)), meters>); + static_assert(std::is_same_v() + length()), length>); + static_assert(std::is_same_v() - length()), length>); + static_assert(std::is_same_v() * 1.0f), length>); + static_assert(std::is_same_v()), length>); + static_assert(std::is_same_v() / 1.0f), length>); + static_assert(std::is_same_v() / length()), float>); + static_assert(std::is_same_v() % short(1)), length>); + static_assert(std::is_same_v() % length(1)), length>); - static_assert((1_m + kilometer).count() == 1001); + static_assert((1_m + km).count() == 1001); static_assert((1_m + 1_km).count() == 1001); - static_assert((kilometer - 1_m).count() == 999); + static_assert((km - 1_m).count() == 999); static_assert((1_km - 1_m).count() == 999); static_assert((2_m * 2).count() == 4); static_assert((3 * 3_m).count() == 9); @@ -237,19 +238,19 @@ namespace { // is_quantity - static_assert(units::detail::is_quantity>::value); + static_assert(units::detail::is_quantity>::value); // common_type - static_assert(std::is_same_v, kilometers>, meters>); - static_assert(std::is_same_v, meters>, meters>); - static_assert(std::is_same_v, millimeters>, millimeters>); + static_assert(std::is_same_v, length>, length>); + static_assert(std::is_same_v, length>, length>); + static_assert(std::is_same_v, length>, length>); // quantity_cast // static_assert(quantity_cast(2_km).count() == 2000); // should not compile - static_assert(quantity_cast>(2_km).count() == 2000); - static_assert(quantity_cast>(2000_m).count() == 2); + static_assert(quantity_cast>(2_km).count() == 2000); + static_assert(quantity_cast>(2000_m).count() == 2); // time diff --git a/test/test_tools.cpp b/test/test_tools.cpp index 46e3f426..46cefacf 100644 --- a/test/test_tools.cpp +++ b/test/test_tools.cpp @@ -20,28 +20,29 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#include "units/si/velocity.h" -#include +#include "units/bits/tools.h" namespace { + using namespace units; + // static_sign - static_assert(mp::static_sign<2>::value == 1); - static_assert(mp::static_sign<-3>::value == -1); - static_assert(mp::static_sign<0>::value == 1); + static_assert(static_sign<2>::value == 1); + static_assert(static_sign<-3>::value == -1); + static_assert(static_sign<0>::value == 1); // static_abs - static_assert(mp::static_abs<2>::value == 2); - static_assert(mp::static_abs<-3>::value == 3); - static_assert(mp::static_abs<0>::value == 0); + static_assert(static_abs<2>::value == 2); + static_assert(static_abs<-3>::value == 3); + static_assert(static_abs<0>::value == 0); // common_ratio - static_assert(std::is_same_v, std::kilo>, std::ratio<1>>); - static_assert(std::is_same_v>, std::ratio<1>>); - static_assert(std::is_same_v, std::milli>, std::milli>); - static_assert(std::is_same_v>, std::milli>); + static_assert(std::is_same_v, std::kilo>, std::ratio<1>>); + static_assert(std::is_same_v>, std::ratio<1>>); + static_assert(std::is_same_v, std::milli>, std::milli>); + static_assert(std::is_same_v>, std::milli>); } // namespace \ No newline at end of file diff --git a/test/test_units.cpp b/test/test_units.cpp index 6b7c67f7..29c352cf 100644 --- a/test/test_units.cpp +++ b/test/test_units.cpp @@ -34,6 +34,7 @@ namespace { static_assert(2 / 1_s == 2_Hz); static_assert(1000 / 1_s == 1_kHz); + static_assert(1 / 1_ms == 1_kHz); static_assert(3.2_GHz == 3'200'000'000_Hz); // time @@ -49,7 +50,7 @@ namespace { // velocity - static_assert(std::is_same_v>>); + static_assert(std::is_same_v>, long long int>>); static_assert(10_m / 5_s == 2_mps); static_assert(10 / 5_s * 1_m == 2_mps); @@ -65,6 +66,6 @@ namespace { static_assert(2_km / 2_kmph == 1_h); // static_assert(2000_m / 2_kmph == 1_h); // should not compile - static_assert(quantity_cast>(2000_m) / 2_kmph == 1_h); + static_assert(quantity_cast>(2000_m) / 2_kmph == 1_h); } // namespace