From 40fb1e1e8bbc9d3a3f6fa268451b8a000d0a6b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Mon, 31 Aug 2020 22:49:43 -0400 Subject: [PATCH 01/12] fix: iwyu --- src/include/units/prefix.h | 1 + src/include/units/quantity_cast.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/include/units/prefix.h b/src/include/units/prefix.h index fbf45665..129be0b3 100644 --- a/src/include/units/prefix.h +++ b/src/include/units/prefix.h @@ -23,6 +23,7 @@ #pragma once #include +#include #include #include diff --git a/src/include/units/quantity_cast.h b/src/include/units/quantity_cast.h index 14bfbd5b..42f3118b 100644 --- a/src/include/units/quantity_cast.h +++ b/src/include/units/quantity_cast.h @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #ifdef _MSC_VER From 2f5be094b223f96d817bbda6fbc2d9e255342376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Mon, 31 Aug 2020 23:19:38 -0400 Subject: [PATCH 02/12] refactor: pow10 functions to pow.h --- src/include/units/pow.h | 61 +++++++++++++++++++++++++++++++ src/include/units/quantity.h | 1 + src/include/units/quantity_cast.h | 33 +---------------- 3 files changed, 63 insertions(+), 32 deletions(-) create mode 100644 src/include/units/pow.h diff --git a/src/include/units/pow.h b/src/include/units/pow.h new file mode 100644 index 00000000..81bc9db2 --- /dev/null +++ b/src/include/units/pow.h @@ -0,0 +1,61 @@ +// 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 +#include + +namespace units { + +constexpr std::intmax_t ipow10(std::intmax_t exp) +{ + assert(exp >= 0); + if (exp == 0) return 1; + std::intmax_t result = 1; + while (exp > 0) { + result *= 10; + --exp; + } + return result; +} + +template +constexpr Rep fpow10(std::intmax_t exp) +{ + if (exp == 0) return Rep(1.0); + Rep result = Rep(1.0); + if (exp < 0) { + while (exp < 0) { + result = result / Rep(10.0); + ++exp; + } + } else { + while (exp > 0) { + result = result * Rep(10.0); + --exp; + } + } + return result; +} + +} // namespace units diff --git a/src/include/units/quantity.h b/src/include/units/quantity.h index 06c46c5c..fce49bd4 100644 --- a/src/include/units/quantity.h +++ b/src/include/units/quantity.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #if COMP_MSVC || COMP_GCC >= 10 diff --git a/src/include/units/quantity_cast.h b/src/include/units/quantity_cast.h index 42f3118b..d741b319 100644 --- a/src/include/units/quantity_cast.h +++ b/src/include/units/quantity_cast.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -37,38 +38,6 @@ namespace units { -constexpr std::intmax_t ipow10(std::intmax_t exp) -{ - assert(exp >= 0); - if (exp == 0) return 1; - std::intmax_t result = 1; - while (exp > 0) { - result *= 10; - --exp; - } - return result; -} - -template -constexpr Rep fpow10(std::intmax_t exp) -{ - if (exp == 0) return Rep(1.0); - Rep result = Rep(1.0); - if (exp < 0) { - while (exp < 0) { - result = result / Rep(10.0); - ++exp; - } - } else { - while (exp > 0) { - result = result * Rep(10.0); - --exp; - } - } - return result; -} - - // QuantityOf template concept QuantityOf = Quantity && Dimension && equivalent_dim; From ca1867c9b2818c6cbc7790809edd07b6e9f1d548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Sat, 5 Sep 2020 18:20:19 -0400 Subject: [PATCH 03/12] refactor!: pow functions as detail --- src/include/units/{ => bits}/pow.h | 4 +-- src/include/units/quantity.h | 6 ++-- src/include/units/quantity_cast.h | 50 +++++++++++++++--------------- 3 files changed, 30 insertions(+), 30 deletions(-) rename src/include/units/{ => bits}/pow.h (96%) diff --git a/src/include/units/pow.h b/src/include/units/bits/pow.h similarity index 96% rename from src/include/units/pow.h rename to src/include/units/bits/pow.h index 81bc9db2..c6693103 100644 --- a/src/include/units/pow.h +++ b/src/include/units/bits/pow.h @@ -25,7 +25,7 @@ #include #include -namespace units { +namespace units::detail { constexpr std::intmax_t ipow10(std::intmax_t exp) { @@ -58,4 +58,4 @@ constexpr Rep fpow10(std::intmax_t exp) return result; } -} // namespace units +} // namespace units::detail diff --git a/src/include/units/quantity.h b/src/include/units/quantity.h index fce49bd4..eb38df01 100644 --- a/src/include/units/quantity.h +++ b/src/include/units/quantity.h @@ -25,8 +25,8 @@ #include #include +#include #include -#include #include #if COMP_MSVC || COMP_GCC >= 10 @@ -343,9 +343,9 @@ template) { - return lhs.count() * rhs.count() * static_cast(r.num * fpow10(r.exp)) / static_cast(r.den); + return lhs.count() * rhs.count() * static_cast(r.num * detail::fpow10(r.exp)) / static_cast(r.den); } else { - return lhs.count() * rhs.count() * static_cast(r.num * ipow10(r.exp)) / static_cast(r.den); + return lhs.count() * rhs.count() * static_cast(r.num * detail::ipow10(r.exp)) / static_cast(r.den); } } diff --git a/src/include/units/quantity_cast.h b/src/include/units/quantity_cast.h index d741b319..79509c50 100644 --- a/src/include/units/quantity_cast.h +++ b/src/include/units/quantity_cast.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -63,13 +63,13 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(static_cast(q.count()) * static_cast(fpow10(CRatio.exp)))); + return To(static_cast(static_cast(q.count()) * static_cast(detail::fpow10(CRatio.exp)))); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(static_cast(q.count()) * static_cast(ipow10(CRatio.exp)))); + return To(static_cast(static_cast(q.count()) * static_cast(detail::ipow10(CRatio.exp)))); } else { - return To(static_cast(static_cast(q.count()) / static_cast(ipow10(-CRatio.exp)))); + return To(static_cast(static_cast(q.count()) / static_cast(detail::ipow10(-CRatio.exp)))); } } } @@ -93,21 +93,21 @@ struct quantity_cast_impl { { if constexpr (treat_as_floating_point) { return To(static_cast(static_cast(q.count()) * - static_cast(fpow10(CRatio.exp)) * + static_cast(detail::fpow10(CRatio.exp)) * (static_cast(CRatio.num) / static_cast(CRatio.den)))); } else { if constexpr (CRatio.exp > 0) { return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) * - static_cast(ipow10(CRatio.exp)) / + static_cast(detail::ipow10(CRatio.exp)) / static_cast(CRatio.den))); } else { return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) / (static_cast(CRatio.den) * - static_cast(ipow10(-CRatio.exp))))); + static_cast(detail::ipow10(-CRatio.exp))))); } } } @@ -128,13 +128,13 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(static_cast(q.count()) * static_cast(fpow10(CRatio.exp)) * (CRep{1} / static_cast(CRatio.den)))); + return To(static_cast(static_cast(q.count()) * static_cast(detail::fpow10(CRatio.exp)) * (CRep{1} / static_cast(CRatio.den)))); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(static_cast(q.count()) * static_cast(ipow10(CRatio.exp)) / static_cast(CRatio.den))); + return To(static_cast(static_cast(q.count()) * static_cast(detail::ipow10(CRatio.exp)) / static_cast(CRatio.den))); } else { - return To(static_cast(static_cast(q.count()) / (static_cast(ipow10(-CRatio.exp)) * static_cast(CRatio.den)))); + return To(static_cast(static_cast(q.count()) / (static_cast(detail::ipow10(-CRatio.exp)) * static_cast(CRatio.den)))); } } } @@ -155,13 +155,13 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) * static_cast(fpow10(CRatio.exp)))); + return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) * static_cast(detail::fpow10(CRatio.exp)))); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) * static_cast(ipow10(CRatio.exp)))); + return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) * static_cast(detail::ipow10(CRatio.exp)))); } else { - return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) / static_cast(ipow10(-CRatio.exp)))); + return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) / static_cast(detail::ipow10(-CRatio.exp)))); } } } @@ -173,13 +173,13 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(q.count() * fpow10(CRatio.exp))); + return To(static_cast(q.count() * detail::fpow10(CRatio.exp))); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(q.count() * ipow10(CRatio.exp))); + return To(static_cast(q.count() * detail::ipow10(CRatio.exp))); } else { - return To(static_cast(q.count() / ipow10(-CRatio.exp))); + return To(static_cast(q.count() / detail::ipow10(-CRatio.exp))); } } } @@ -200,13 +200,13 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(q.count() * fpow10(CRatio.exp) * (CRatio.num / CRatio.den))); + return To(static_cast(q.count() * detail::fpow10(CRatio.exp) * (CRatio.num / CRatio.den))); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(q.count() * CRatio.num * ipow10(CRatio.exp) / CRatio.den)); + return To(static_cast(q.count() * CRatio.num * detail::ipow10(CRatio.exp) / CRatio.den)); } else { - return To(static_cast(q.count()) * CRatio.num / (CRatio.den * ipow10(-CRatio.exp))); + return To(static_cast(q.count()) * CRatio.num / (CRatio.den * detail::ipow10(-CRatio.exp))); } } } @@ -227,13 +227,13 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(q.count() * fpow10(CRatio.exp) / CRatio.den)); + return To(static_cast(q.count() * detail::fpow10(CRatio.exp) / CRatio.den)); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(q.count() * ipow10(CRatio.exp) / CRatio.den)); + return To(static_cast(q.count() * detail::ipow10(CRatio.exp) / CRatio.den)); } else { - return To(static_cast(q.count() / (ipow10(-CRatio.exp) * CRatio.den))); + return To(static_cast(q.count() / (detail::ipow10(-CRatio.exp) * CRatio.den))); } } } @@ -254,13 +254,13 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(q.count() * CRatio.num * fpow10(CRatio.exp))); + return To(static_cast(q.count() * CRatio.num * detail::fpow10(CRatio.exp))); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(q.count() * CRatio.num * ipow10(CRatio.exp))); + return To(static_cast(q.count() * CRatio.num * detail::ipow10(CRatio.exp))); } else { - return To(static_cast(q.count() * CRatio.num / ipow10(-CRatio.exp))); + return To(static_cast(q.count() * CRatio.num / detail::ipow10(-CRatio.exp))); } } } From 9f9397ffc285a354a136f46b013e3e3270b885d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Sat, 5 Sep 2020 21:41:02 -0400 Subject: [PATCH 04/12] test: convert comments to code --- test/unit_test/static/quantity_point_test.cpp | 2 +- test/unit_test/static/quantity_test.cpp | 73 ++++++++++++------- 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/test/unit_test/static/quantity_point_test.cpp b/test/unit_test/static/quantity_point_test.cpp index 424d785f..c03ba222 100644 --- a/test/unit_test/static/quantity_point_test.cpp +++ b/test/unit_test/static/quantity_point_test.cpp @@ -47,7 +47,7 @@ concept invalid_types = requires !requires { typename quantity; }; // reordered arguments }; -static_assert(invalid_types); +static_assert(invalid_types); // member types diff --git a/test/unit_test/static/quantity_test.cpp b/test/unit_test/static/quantity_test.cpp index 3e4b20f4..3e80b688 100644 --- a/test/unit_test/static/quantity_test.cpp +++ b/test/unit_test/static/quantity_test.cpp @@ -36,11 +36,18 @@ using namespace units::physical::si; // class invariants -// constexpr quantity error(0); // should not compile (unit of a different dimension) -// constexpr quantity> error(0); // should not compile (quantity used as Rep) -// constexpr quantity error(0); // should not compile (reordered arguments) // constexpr quantity, int> error(0); // should not compile (negative unit ratio) +template +concept invalid_types = requires +{ + !requires { typename quantity; }; // unit of a different dimension + !requires { typename quantity>; }; // quantity used as Rep + !requires { typename quantity; }; // reordered arguments +}; + +static_assert(invalid_types); + // member types static_assert(is_same_v::rep, int>); @@ -56,18 +63,21 @@ static_assert(km.count() == 1000); static_assert(length(km).count() == km.count()); static_assert(length(1).count() == 1); -// static_assert(length(1.0).count() == 1); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v, double>); // truncating conversion static_assert(length(1.0).count() == 1.0); static_assert(length(1).count() == 1.0); static_assert(length(3.14).count() == 3.14); static_assert(length(km).count() == 1000); -// static_assert(length(length(3.14)).count() == 3); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v, + length>); // truncating conversion static_assert(length(1000.0q_m).count() == 1000.0); static_assert(length(km).count() == 1000.0); static_assert(length(1q_km).count() == 1000); -// static_assert(length(1q_s).count() == 1); // should not compile (different dimensions) -//static_assert(length(1010q_m).count() == 1); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v, + physical::si::time>); // different dimensions +static_assert(!std::is_constructible_v, + length>); // truncating conversion // assignment operator @@ -89,24 +99,22 @@ 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); -}(km) == std::make_pair(length(1001), length(1000))); + return std::pair(v, vv); +}(km) == std::pair(length(1001), length(1000))); static_assert([](auto v) { auto vv = ++v; - return std::make_pair(v, vv); -}(km) == std::make_pair(length(1001), length(1001))); + return std::pair(v, vv); +}(km) == std::pair(length(1001), length(1001))); static_assert([](auto v) { auto vv = v--; - return std::make_pair(v, vv); -}(km) == std::make_pair(length(999), length(1000))); + return std::pair(v, vv); +}(km) == std::pair(length(999), length(1000))); static_assert([](auto v) { auto vv = --v; - return std::make_pair(v, vv); -}(km) == std::make_pair(length(999), length(999))); + return std::pair(v, vv); +}(km) == std::pair(length(999), length(999))); // compound assignment @@ -116,22 +124,29 @@ static_assert((1q_m *= 2).count() == 2); static_assert((2q_m /= 2).count() == 1); static_assert((7q_m %= 2).count() == 1); static_assert((7q_m %= 2q_m).count() == 1); -// static_assert((7.m %= 2.).count() == 1); // should not compile (operation not allowed for floating-point types) -// static_assert((7.m %= 2).count() == 1); // should not compile (operation not allowed for floating-point types) -// static_assert((7q_m %= 2.).count() == 1); // should not compile (operation not allowed for floating-point types) -static_assert((7q_m %= 2q_m).count() == 1); -// static_assert((7.m %= 2.m).count() == 1); // should not compile (operation not allowed for floating-point types) -// static_assert((7.m %= 2q_m).count() == 1); // should not compile (operation not allowed for floating-point types) -// static_assert((7q_m %= 2.m).count() == 1); // should not compile (operation not allowed for floating-point types) -// static_assert(2q_m += 3.5q_m); // should not compile static_assert((2.5q_m += 3q_m).count() == 5.5); static_assert((2.5q_m += 3.5q_m).count() == 6); -// static_assert(2q_m *= 3.5); // should not compile static_assert((2.5q_m *= 3).count() == 7.5); static_assert((2.5q_m *= 3.5).count() == 8.75); +// operations not allowed for the respective quantities +template +concept invalid_compound_assignments = requires() +{ + !requires(length l) { l %= 2.; }; + !requires(length l) { l %= 2; }; + !requires(length l) { l %= 2.; }; + !requires(length l) { l %= 2.q_m; }; + !requires(length l) { l %= 2q_m; }; + !requires(length l) { l %= 2.q_m; }; + !requires(length l) { l += 3.5q_m; }; + !requires(length l) { l *= 3.5q_m; }; +}; + +static_assert(invalid_compound_assignments); + // non-member arithmetic operators static_assert(is_same_v() + length()), length>); @@ -253,9 +268,13 @@ static_assert(quantity_cast(1.23q_m).count() == 1); // time -// static_assert(1q_s == 1q_m); // should not compile (different dimensions) static_assert(1q_h == 3600q_s); +template +constexpr bool no_crossdimensional_equality = !requires { 1q_s == length(1); }; + +static_assert(no_crossdimensional_equality); + // length static_assert(1q_km == 1000q_m); From 71eda2fc66724e3e5a28e3bd71b4bbb37da22aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Sat, 5 Sep 2020 22:22:18 -0400 Subject: [PATCH 05/12] test: codify comment in the correct place --- test/unit_test/static/quantity_test.cpp | 2 -- test/unit_test/static/unit_test.cpp | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/test/unit_test/static/quantity_test.cpp b/test/unit_test/static/quantity_test.cpp index 3e80b688..dcc9d7bf 100644 --- a/test/unit_test/static/quantity_test.cpp +++ b/test/unit_test/static/quantity_test.cpp @@ -36,8 +36,6 @@ using namespace units::physical::si; // class invariants -// constexpr quantity, int> error(0); // should not compile (negative unit ratio) - template concept invalid_types = requires { diff --git a/test/unit_test/static/unit_test.cpp b/test/unit_test/static/unit_test.cpp index a48a1e86..125db502 100644 --- a/test/unit_test/static/unit_test.cpp +++ b/test/unit_test/static/unit_test.cpp @@ -51,6 +51,9 @@ static_assert(is_same_v>, centimetr static_assert(is_same_v>, yard>); static_assert(is_same_v>, foot>); static_assert(is_same_v>, kilometre_per_hour>); +#if COMP_MSVC || COMP_GCC >= 10 +static_assert([]() { return !requires { typename scaled_unit; }; }.template operator()()); // negative unit ratio +#endif static_assert(centimetre::symbol == "cm"); static_assert(kilometre::symbol == "km"); From 45cf2dcf885428013cf2635c3a3d4279105173a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Sat, 5 Sep 2020 22:39:25 -0400 Subject: [PATCH 06/12] test: remove outdated comment --- test/unit_test/static/ratio_test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit_test/static/ratio_test.cpp b/test/unit_test/static/ratio_test.cpp index 2c05828b..4284439c 100644 --- a/test/unit_test/static/ratio_test.cpp +++ b/test/unit_test/static/ratio_test.cpp @@ -29,7 +29,6 @@ using namespace units; static_assert(ratio(2, 4) == ratio(1, 2)); // basic exponents tests -// note use of ::type is required because template params are changed while stamping out template static_assert(ratio(2, 40, 1) == ratio(1, 20, 1)); static_assert(ratio(20, 4, -1) == ratio(10, 2, -1)); static_assert(ratio(200, 5) == ratio(20'000, 50, -1)); From aff83b31dc56ac3d14f648bf893470a062706364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Sat, 5 Sep 2020 22:39:34 -0400 Subject: [PATCH 07/12] test: codify comment --- test/unit_test/static/unit_test.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/unit_test/static/unit_test.cpp b/test/unit_test/static/unit_test.cpp index 125db502..23ca50d6 100644 --- a/test/unit_test/static/unit_test.cpp +++ b/test/unit_test/static/unit_test.cpp @@ -40,6 +40,9 @@ struct hour : named_scaled_unit { struct dim_time : base_dimension<"time", second> {}; struct kelvin : named_unit {}; +#if COMP_MSVC || COMP_GCC >= 10 +static_assert([]() { return !requires { typename prefixed_unit; }; }.template operator()()); // negative unit ratio +#endif // struct kilokelvin : prefixed_unit {}; // should not compile (prefix not allowed for this reference unit) struct metre_per_second : unit {}; From 4aeb9d305ac76cbe719f8a4294b397385bc85b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Sat, 5 Sep 2020 22:53:19 -0400 Subject: [PATCH 08/12] test: what we mean a concept can fail for whatever requirement, and maybe the "main" one actually works (== in this case) --- test/unit_test/static/quantity_point_test.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/unit_test/static/quantity_point_test.cpp b/test/unit_test/static/quantity_point_test.cpp index c03ba222..48267bfc 100644 --- a/test/unit_test/static/quantity_point_test.cpp +++ b/test/unit_test/static/quantity_point_test.cpp @@ -226,12 +226,16 @@ static_assert(quantity_point_cast(quantity_point(1.23q_m)).relative().count // time -#if COMP_MSVC || COMP_GCC >= 10 -static_assert(!std::equality_comparable_with, - quantity_point>); // different dimensions -#endif static_assert(quantity_point{1q_h} == quantity_point{3600q_s}); +template +constexpr bool no_crossdimensional_equality = !requires +{ + quantity_point(1q_s) == quantity_point(length(1)); +}; + +static_assert(no_crossdimensional_equality); + // length static_assert(quantity_point(1q_km) == quantity_point(1000q_m)); From 36046fb6a6bc6a733e2807779cfd4c6f82b051c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Sat, 5 Sep 2020 22:55:59 -0400 Subject: [PATCH 09/12] test: simplify case --- test/unit_test/static/unit_test.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/unit_test/static/unit_test.cpp b/test/unit_test/static/unit_test.cpp index 23ca50d6..f13d0ac6 100644 --- a/test/unit_test/static/unit_test.cpp +++ b/test/unit_test/static/unit_test.cpp @@ -41,9 +41,8 @@ struct dim_time : base_dimension<"time", second> {}; struct kelvin : named_unit {}; #if COMP_MSVC || COMP_GCC >= 10 -static_assert([]() { return !requires { typename prefixed_unit; }; }.template operator()()); // negative unit ratio +static_assert([](P) { return !requires { typename prefixed_unit; }; }(si::kilo{})); // negative unit ratio #endif -// struct kilokelvin : prefixed_unit {}; // should not compile (prefix not allowed for this reference unit) struct metre_per_second : unit {}; struct dim_speed : derived_dimension, units::exp> {}; From 411241472992301f14da30471a89618bce62c5f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Sun, 6 Sep 2020 01:10:11 -0400 Subject: [PATCH 10/12] test: nonzero denominator --- test/unit_test/static/ratio_test.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/unit_test/static/ratio_test.cpp b/test/unit_test/static/ratio_test.cpp index 4284439c..4b4d044f 100644 --- a/test/unit_test/static/ratio_test.cpp +++ b/test/unit_test/static/ratio_test.cpp @@ -88,4 +88,10 @@ static_assert(common_ratio(ratio(100, 1), ratio(1, 10)) == ratio(1, 10)); static_assert(common_ratio(ratio(1), ratio(1, 1, 3)) == ratio(1)); static_assert(common_ratio(ratio(10, 1, -1), ratio(1, 1, -3)) == ratio(1, 1, -3)); +// nonzero denominator +template struct require_constant; // [range.split.view] +template concept constant = requires { typename require_constant; }; + +static_assert(!constant<[] { ratio(1, 0); }>); + } // namespace From c09dbb1756ab8cb9323be4cc163e8c2cb838090e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Sun, 6 Sep 2020 01:33:47 -0400 Subject: [PATCH 11/12] test: add missing explicit specifier --- test/unit_test/static/custom_rep_min_req_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit_test/static/custom_rep_min_req_test.cpp b/test/unit_test/static/custom_rep_min_req_test.cpp index d9a12ce5..8f7783b8 100644 --- a/test/unit_test/static/custom_rep_min_req_test.cpp +++ b/test/unit_test/static/custom_rep_min_req_test.cpp @@ -65,7 +65,7 @@ template struct expl_constructible : scalar_ops> { T value_{}; expl_constructible() = default; - constexpr expl_constructible(T v) : value_(std::move(v)) {} + constexpr explicit expl_constructible(T v) : value_(std::move(v)) {} // no conversion to fundamental arithmetic types }; From f1f23aa8f9d2fa8157620334721c5e38f38d0805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johel=20Ernesto=20Guerrero=20Pe=C3=B1a?= Date: Sun, 6 Sep 2020 03:00:33 -0400 Subject: [PATCH 12/12] test: codify comments --- .../static/custom_rep_min_req_test.cpp | 69 ++++++++++--------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/test/unit_test/static/custom_rep_min_req_test.cpp b/test/unit_test/static/custom_rep_min_req_test.cpp index 8f7783b8..2f50c244 100644 --- a/test/unit_test/static/custom_rep_min_req_test.cpp +++ b/test/unit_test/static/custom_rep_min_req_test.cpp @@ -25,6 +25,7 @@ #include "units/physical/si/frequency.h" #include "units/physical/si/speed.h" #include +#include #include using namespace units; @@ -172,60 +173,60 @@ using namespace units::physical::si; // Quantity from Scalar // int <- int static_assert(length(expl_impl(1)).count() == 1); -// static_assert(length(impl_expl(1)).count() == 1); // should not compile (not convertible) +static_assert(!std::is_constructible_v, impl_expl>); static_assert(length(int(impl_expl(1))).count() == 1); -// static_assert(length>(1).count() == expl_impl{1}); // should not compile (not convertible) +static_assert(!std::is_constructible_v>, int>); static_assert(length>(expl_impl(1)).count() == expl_impl{1}); static_assert(length>(1).count() == impl_expl{1}); // double <- double static_assert(length(expl_impl(1.0)).count() == 1.0); -// static_assert(length(impl_expl(1.0)).count() == 1.0); // should not compile (not convertible) +static_assert(!std::is_constructible_v, impl_expl>); static_assert(length(double(impl_expl(1.0))).count() == 1.0); -// static_assert(length>(1.0).count() == expl_impl{1.0}); // should not compile (not convertible) +static_assert(!std::is_constructible_v>, double>); static_assert(length>(expl_impl(1.0)).count() == expl_impl{1.0}); static_assert(length>(1.0).count() == impl_expl{1.0}); // double <- int static_assert(length(expl_impl(1)).count() == 1.0); -// static_assert(length(impl_expl(1)).count() == 1.0); // should not compile (not convertible) +static_assert(!std::is_constructible_v, impl_expl>); static_assert(length(int(impl_expl(1))).count() == 1.0); -// static_assert(length>(1).count() == expl_impl{1}); // should not compile (not convertible) +static_assert(!std::is_constructible_v>, int>); static_assert(length>(expl_impl(1)).count() == expl_impl{1}); static_assert(length>(1).count() == impl_expl{1.0}); // int <- double -// static_assert(length(expl_impl(1.0)).count() == 1); // should not compile (truncating conversion) -// static_assert(length>(1.0).count() == impl_expl{1}); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v, expl_impl>); +static_assert(!std::is_constructible_v>, double>); // Quantity from other Quantity with different Rep // int <- int static_assert(length(length>(expl_impl(1))).count() == 1); -// static_assert(length(length>(1)).count() == 1); // should not compile (not convertible) +static_assert(!std::is_constructible_v, length>>); static_assert(length(quantity_cast(length>(1))).count() == 1); -// static_assert(length>(length(1)).count() == expl_impl{1}); // should not compile (not convertible) +static_assert(!std::is_constructible_v>, length>); static_assert(length>(quantity_cast>(length(1))).count() == expl_impl{1}); static_assert(length>(length(1)).count() == impl_expl{1}); // double <- double static_assert(length(length>(expl_impl(1.0))).count() == 1.0); -// static_assert(length(length>(1.0)).count() == 1.0); // should not compile (not convertible) +static_assert(!std::is_constructible_v, length>>); static_assert(length(quantity_cast(length>(1.0))).count() == 1.0); -// static_assert(length>(length(1.0).count() == expl_impl{1.0}); // should not compile (not convertible) +static_assert(!std::is_constructible_v>, length>); static_assert(length>(quantity_cast>(length(1.0))).count() == expl_impl{1.0}); static_assert(length>(length(1.0)).count() == impl_expl{1.0}); // double <- int static_assert(length(length>(expl_impl(1))).count() == 1.0); -// static_assert(length(length>(1)).count() == 1.0); // should not compile (not convertible) +static_assert(!std::is_constructible_v, length>>); static_assert(length(quantity_cast(length>(1))).count() == 1.0); -// static_assert(length>(length(1)).count() == expl_impl{1}); // should not compile (not convertible) +static_assert(!std::is_constructible_v>, length>); static_assert(length>(quantity_cast>(length(1))).count() == expl_impl{1}); static_assert(length>(length(1)).count() == impl_expl{1.0}); // int <- double -// static_assert(length(length>(1.0)).count() == 1); // should not compile (truncating conversion) -// static_assert(length>(length(1.0)).count() == impl_expl{1}); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v, length>>); +static_assert(!std::is_constructible_v>, length>); // unit conversions @@ -236,43 +237,43 @@ static_assert(length>(length>(1) static_assert(length>(length>(expl_impl(1))).count() == expl_impl(1000)); static_assert(length>(length>(expl_expl(1))).count() == expl_expl(1000)); -// static_assert(length>(length>(2000)).count() == impl(2)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, length>>); static_assert(length>(quantity_cast(length>(2000))).count() == impl(2)); -// static_assert(length>(length>(expl(2000))).count() == expl(2)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, length>>); static_assert(length>(quantity_cast(length>(expl(2000)))).count() == expl(2)); -// static_assert(length>(length>(2000)).count() == impl_impl(2)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, length>>); static_assert(length>(quantity_cast(length>(2000))).count() == impl_impl(2)); -// static_assert(length>(length>(2000)).count() == impl_expl(2)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, length>>); static_assert(length>(quantity_cast(length>(2000))).count() == impl_expl(2)); -// static_assert(length>(length>(expl_impl(2000))).count() == expl_impl(2)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, length>>); static_assert(length>(quantity_cast(length>(expl_impl(2000)))).count() == expl_impl(2)); -// static_assert(length>(length>(expl_expl(2000))).count() == expl_expl(2)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, length>>); static_assert(length>(quantity_cast(length>(expl_expl(2000)))).count() == expl_expl(2)); -// static_assert(speed>(speed>(72)).count() == impl(20)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, speed>>); static_assert(speed>(quantity_cast(speed>(72))).count() == impl(20)); -// static_assert(speed>(speed>(expl(72))).count() == expl(20)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, speed>>); static_assert(speed>(quantity_cast(speed>(expl(72)))).count() == expl(20)); -// static_assert(speed>(speed>(72)).count() == impl_impl(20)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, speed>>); static_assert(speed>(quantity_cast(speed>(72))).count() == impl_impl(20)); -// static_assert(speed>(speed>(72)).count() == impl_expl(20)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, speed>>); static_assert(speed>(quantity_cast(speed>(72))).count() == impl_expl(20)); -// static_assert(speed>(speed>(expl_impl(72))).count() == expl_impl(20)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, speed>>); static_assert(speed>(quantity_cast(speed>(expl_impl(72)))).count() == expl_impl(20)); -// static_assert(speed>(speed>(expl_expl(72))).count() == expl_expl(20)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, speed>>); static_assert(speed>(quantity_cast(speed>(expl_expl(72)))).count() == expl_expl(20)); -// static_assert(speed>(speed>(20)).count() == impl(72)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, speed>>); static_assert(speed>(quantity_cast(speed>(20))).count() == impl(72)); -// static_assert(speed>(speed>(expl(20))).count() == expl(72)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, speed>>); static_assert(speed>(quantity_cast(speed>(expl(20)))).count() == expl(72)); -// static_assert(speed>(speed>(20)).count() == impl_impl(72)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, speed>>); static_assert(speed>(quantity_cast(speed>(20))).count() == impl_impl(72)); -// static_assert(speed>(speed>(20)).count() == impl_expl(72)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, speed>>); static_assert(speed>(quantity_cast(speed>(20))).count() == impl_expl(72)); -// static_assert(speed>(speed>(expl_impl(20))).count() == expl_impl(72)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, speed>>); static_assert(speed>(quantity_cast(speed>(expl_impl(20)))).count() == expl_impl(72)); -// static_assert(speed>(speed>(expl_expl(20))).count() == expl_expl(72)); // should not compile (truncating conversion) +static_assert(!std::is_constructible_v>, speed>>); static_assert(speed>(quantity_cast(speed>(expl_expl(20)))).count() == expl_expl(72)); } // namespace