fix: add quantity_point::origin, like std::chrono::time_point::clock

This commit is contained in:
Johel Ernesto Guerrero Peña
2021-06-29 20:44:27 +02:00
committed by Mateusz Pusz
parent 7ed29807a6
commit 80eefec97c
26 changed files with 542 additions and 208 deletions
+1
View File
@@ -51,6 +51,7 @@ add_library(unit_tests_static
iec80000_test.cpp
kind_test.cpp
math_test.cpp
point_origin_test.cpp
ratio_test.cpp
references_test.cpp
si_test.cpp
+22 -19
View File
@@ -36,7 +36,7 @@ using namespace std::chrono_literals;
using sys_seconds = std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>;
using sys_days = std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<long, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>>;
template<typename U, typename Rep = double> using time_point = quantity_point<si::dim_time, U, Rep>;
template<typename C, typename U, typename Rep = double> using time_point = quantity_point<clock_origin<C>, U, Rep>;
static_assert(QuantityLike<std::chrono::seconds>);
static_assert(QuantityPointLike<sys_seconds>);
@@ -50,14 +50,17 @@ static_assert(std::constructible_from<si::time<si::second, std::chrono::hours::r
static_assert(!std::convertible_to<std::chrono::hours, si::time<si::second, std::chrono::hours::rep>>);
static_assert(!std::constructible_from<si::time<si::hour, std::chrono::seconds::rep>, std::chrono::seconds>);
static_assert(!std::convertible_to<std::chrono::seconds, si::time<si::hour, std::chrono::seconds::rep>>);
static_assert(std::constructible_from<time_point<si::second, sys_seconds::rep>, sys_seconds>);
static_assert(!std::convertible_to<sys_seconds, time_point<si::second, sys_seconds::rep>>);
static_assert(std::constructible_from<time_point<si::day, sys_days::rep>, sys_days>);
static_assert(!std::convertible_to<sys_days, time_point<si::day, sys_days::rep>>);
static_assert(std::constructible_from<time_point<si::second, sys_days::rep>, sys_days>);
static_assert(!std::convertible_to<sys_days, time_point<si::second, sys_days::rep>>);
static_assert(!std::constructible_from<time_point<si::day, sys_seconds::rep>, sys_seconds>);
static_assert(!std::convertible_to<sys_seconds, time_point<si::day, sys_seconds::rep>>);
static_assert(std::constructible_from<time_point<std::chrono::system_clock, si::second, sys_seconds::rep>, sys_seconds>);
static_assert(!std::constructible_from<time_point<std::chrono::steady_clock, si::second, sys_seconds::rep>, sys_seconds>);
static_assert(!std::convertible_to<sys_seconds, time_point<std::chrono::system_clock, si::second, sys_seconds::rep>>);
static_assert(std::constructible_from<time_point<std::chrono::system_clock, si::day, sys_days::rep>, sys_days>);
static_assert(!std::constructible_from<time_point<std::chrono::steady_clock, si::day, sys_days::rep>, sys_days>);
static_assert(!std::convertible_to<sys_days, time_point<std::chrono::system_clock, si::day, sys_days::rep>>);
static_assert(std::constructible_from<time_point<std::chrono::system_clock, si::second, sys_days::rep>, sys_days>);
static_assert(!std::constructible_from<time_point<std::chrono::steady_clock, si::second, sys_days::rep>, sys_days>);
static_assert(!std::convertible_to<sys_days, time_point<std::chrono::system_clock, si::second, sys_days::rep>>);
static_assert(!std::constructible_from<time_point<std::chrono::system_clock, si::day, sys_seconds::rep>, sys_seconds>);
static_assert(!std::convertible_to<sys_seconds, time_point<std::chrono::system_clock, si::day, sys_seconds::rep>>);
// construction - different rep type (integral to a floating-point)
static_assert(std::constructible_from<si::time<si::second>, std::chrono::seconds>);
@@ -66,25 +69,25 @@ static_assert(std::constructible_from<si::time<si::second>, std::chrono::hours>)
static_assert(!std::convertible_to<std::chrono::hours, si::time<si::second>>);
static_assert(std::constructible_from<si::time<si::hour>, std::chrono::seconds>);
static_assert(!std::convertible_to<std::chrono::seconds, si::time<si::hour>>);
static_assert(std::constructible_from<time_point<si::second>, sys_seconds>);
static_assert(!std::convertible_to<sys_seconds, time_point<si::second>>);
static_assert(std::constructible_from<time_point<si::second>, sys_days>);
static_assert(!std::convertible_to<sys_days, time_point<si::second>>);
static_assert(std::constructible_from<time_point<si::day>, sys_seconds>);
static_assert(!std::convertible_to<sys_seconds, time_point<si::day>>);
static_assert(std::constructible_from<time_point<std::chrono::system_clock, si::second>, sys_seconds>);
static_assert(!std::convertible_to<sys_seconds, time_point<std::chrono::system_clock, si::second>>);
static_assert(std::constructible_from<time_point<std::chrono::system_clock, si::second>, sys_days>);
static_assert(!std::convertible_to<sys_days, time_point<std::chrono::system_clock, si::second>>);
static_assert(std::constructible_from<time_point<std::chrono::system_clock, si::day>, sys_seconds>);
static_assert(!std::convertible_to<sys_seconds, time_point<std::chrono::system_clock, si::day>>);
// CTAD
static_assert(is_same_v<decltype(quantity{1s}), si::time<si::second, std::chrono::seconds::rep>>);
static_assert(is_same_v<decltype(quantity{1h}), si::time<si::hour, std::chrono::hours::rep>>);
static_assert(is_same_v<decltype(quantity_point{sys_seconds{1s}}), time_point<si::second, sys_seconds::rep>>);
static_assert(is_same_v<decltype(quantity_point{sys_days{sys_days::duration{1}}}), time_point<si::day, sys_days::rep>>);
static_assert(is_same_v<decltype(quantity_point{sys_seconds{1s}}), time_point<std::chrono::system_clock, si::second, sys_seconds::rep>>);
static_assert(is_same_v<decltype(quantity_point{sys_days{sys_days::duration{1}}}), time_point<std::chrono::system_clock, si::day, sys_days::rep>>);
// operators
static_assert(quantity{1s} + 1_q_s == 2_q_s);
static_assert(quantity{1s} + 1_q_min == 61_q_s);
static_assert(10_q_m / quantity{2s} == 5_q_m_per_s);
static_assert(quantity_point{sys_seconds{1s}} + 1_q_s == quantity_point{2_q_s});
static_assert(quantity_point{sys_seconds{1s}} + 1_q_min == quantity_point{61_q_s});
static_assert(quantity_point{sys_seconds{1s}} + 1_q_s == time_point<std::chrono::system_clock, si::second>{2_q_s});
static_assert(quantity_point{sys_seconds{1s}} + 1_q_min == time_point<std::chrono::system_clock, si::second>{61_q_s});
} // namespace
+8 -3
View File
@@ -27,7 +27,7 @@
#include <units/isq/si/length.h> // IWYU pragma: keep
#include <units/isq/si/prefixes.h>
#include <units/isq/si/speed.h>
#include <units/quantity_point.h>
#include <units/quantity_point_kind.h>
#include <units/chrono.h>
#include <chrono>
#include <complex>
@@ -112,11 +112,11 @@ static_assert(!Representation<std::string>);
static_assert(Quantity<si::length<si::metre>>);
static_assert(!Quantity<std::chrono::seconds>);
static_assert(!Quantity<quantity_point<si::dim_length, si::metre>>);
static_assert(!Quantity<quantity_point<dynamic_origin<si::dim_length>, si::metre>>);
// QuantityPoint
static_assert(QuantityPoint<quantity_point<si::dim_length, si::metre>>);
static_assert(QuantityPoint<quantity_point<dynamic_origin<si::dim_length>, si::metre>>);
static_assert(!QuantityPoint<si::length<si::metre>>);
static_assert(!QuantityPoint<std::chrono::seconds>);
@@ -141,4 +141,9 @@ static_assert(QuantityOf<si::cgs::length<si::metre>, si::dim_length>);
static_assert(QuantityOf<si::cgs::length<si::cgs::centimetre>, si::fps::dim_length>);
static_assert(!QuantityOf<si::cgs::length<si::cgs::centimetre>, si::dim_time>);
static_assert(QuantityPointOf<quantity_point<dynamic_origin<si::dim_time>, si::second, int>, dynamic_origin<si::dim_time>>);
static_assert(QuantityPointOf<quantity_point<clock_origin<std::chrono::system_clock>, si::second, int>, clock_origin<std::chrono::system_clock>>);
static_assert(!QuantityPointOf<quantity_point<dynamic_origin<si::dim_time>, si::second, int>, clock_origin<std::chrono::system_clock>>);
static_assert(!QuantityPointOf<quantity_point<clock_origin<std::chrono::system_clock>, si::second, int>, dynamic_origin<si::dim_time>>);
} // namespace
+1 -2
View File
@@ -28,6 +28,7 @@
#include <units/isq/si/length.h>
#include <units/isq/si/speed.h>
#include <units/kind.h>
#include <units/quantity_point.h>
#include <type_traits>
using namespace units;
@@ -97,7 +98,6 @@ static_assert(PointKind<radial_point>);
static_assert(is_same_v<radial_point::base_kind, radius>);
static_assert(is_same_v<radial_point::dimension, dim_length>);
static_assert(is_same_v<radial_point, detail::_point_kind_base<radius>>);
static_assert(is_same_v<radial_point, downcast_point_kind<radius>>);
static_assert(equivalent<radial_point, radial_point>);
@@ -137,7 +137,6 @@ static_assert(PointKind<horizontal_velocity>);
static_assert(is_same_v<horizontal_velocity::base_kind, horizontal_speed>);
static_assert(is_same_v<horizontal_velocity::dimension, dim_speed>);
static_assert(is_same_v<horizontal_velocity, detail::_point_kind_base<horizontal_speed>>);
static_assert(is_same_v<horizontal_velocity, downcast_point_kind<horizontal_speed>>);
static_assert(equivalent<horizontal_velocity, horizontal_velocity>);
@@ -0,0 +1,73 @@
// 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 <units/bits/equivalent.h>
#include <units/chrono.h>
#include <units/kind.h>
#include <units/quantity_point.h>
#include <units/isq/si/length.h>
#include <units/isq/si/cgs/length.h>
using namespace units;
namespace si = isq::si;
namespace {
struct width : kind<width, si::dim_length> {};
struct ones_viewpoint1 : point_origin<si::dim_length> {
template<typename D>
using rebind = ones_viewpoint1;
};
struct ones_viewpoint2 : point_origin<si::cgs::dim_length> {
template<typename D>
using rebind = ones_viewpoint1;
};
static_assert(PointOrigin<dynamic_origin<si::dim_length>>);
static_assert(!PointOrigin<point_origin<si::dim_length>>);
static_assert(!PointOrigin<width>);
static_assert(!PointOrigin<point_kind<struct abscissa, width>>);
static_assert(RebindablePointOriginFor<dynamic_origin<si::dim_length>, si::dim_length>);
static_assert(is_same_v<rebind_point_origin_dimension<dynamic_origin<si::dim_length>, si::dim_length>,
dynamic_origin<si::dim_length>>);
static_assert(RebindablePointOriginFor<dynamic_origin<si::dim_length>, si::dim_time>);
static_assert(is_same_v<rebind_point_origin_dimension<dynamic_origin<si::dim_length>, si::dim_time>,
dynamic_origin<si::dim_time>>);
static_assert(RebindablePointOriginFor<ones_viewpoint1, si::dim_length>);
static_assert(is_same_v<rebind_point_origin_dimension<ones_viewpoint1, si::dim_length>, ones_viewpoint1>);
static_assert(RebindablePointOriginFor<ones_viewpoint2, si::dim_length>);
static_assert(is_same_v<rebind_point_origin_dimension<ones_viewpoint2, si::dim_length>, ones_viewpoint1>);
static_assert(RebindablePointOriginFor<ones_viewpoint2, si::cgs::dim_length>);
static_assert(is_same_v<rebind_point_origin_dimension<ones_viewpoint2, si::cgs::dim_length>, ones_viewpoint2>);
static_assert(!RebindablePointOriginFor<ones_viewpoint1, si::cgs::dim_length>);
static_assert(equivalent<dynamic_origin<si::dim_time>, dynamic_origin<si::dim_time>>);
static_assert(equivalent<dynamic_origin<si::dim_length>, dynamic_origin<si::cgs::dim_length>>);
static_assert(!equivalent<dynamic_origin<si::dim_time>, clock_origin<std::chrono::system_clock>>);
static_assert(!equivalent<clock_origin<std::chrono::steady_clock>, clock_origin<std::chrono::system_clock>>);
static_assert(!equivalent<dynamic_origin<si::dim_time>, dynamic_origin<si::dim_length>>);
static_assert(!equivalent<ones_viewpoint1, ones_viewpoint2>);
} // namespace
+15 -15
View File
@@ -82,16 +82,16 @@ static_assert(QuantityKind<width<metre>>);
static_assert(QuantityKind<rate_of_climb<metre_per_second>>);
static_assert(!QuantityKind<double>);
static_assert(!QuantityKind<length<metre>>);
static_assert(!QuantityKind<quantity_point<dim_length, metre>>);
static_assert(!QuantityKind<quantity_point<dynamic_origin<dim_length>, metre>>);
static_assert(QuantityKindOf<width<metre>, width_kind>);
static_assert(!QuantityKindOf<width<metre>, height_kind>);
static_assert(!QuantityKindOf<width<metre>, metre>);
static_assert(!QuantityKindOf<length<metre>, width_kind>);
static_assert(!QuantityKindOf<length<metre>, metre>);
static_assert(!QuantityKindOf<quantity_point<dim_length, metre>, width_kind>);
static_assert(!QuantityKindOf<quantity_point<dim_length, metre>, dim_length>);
static_assert(!QuantityKindOf<quantity_point<dim_length, metre>, metre>);
static_assert(!QuantityKindOf<quantity_point<dynamic_origin<dim_length>, metre>, width_kind>);
static_assert(!QuantityKindOf<quantity_point<dynamic_origin<dim_length>, metre>, dim_length>);
static_assert(!QuantityKindOf<quantity_point<dynamic_origin<dim_length>, metre>, metre>);
///////////////
@@ -105,7 +105,7 @@ template<typename Width>
concept invalid_types = requires {
requires !requires { typename quantity_kind<Width, second, int>; }; // unit of a different dimension
requires !requires { typename quantity_kind<Width, metre, length<metre>>; }; // quantity used as Rep
requires !requires { typename quantity_kind<Width, metre, quantity_point<dim_length, metre>>; }; // quantity point used as Rep
requires !requires { typename quantity_kind<Width, metre, quantity_point<dynamic_origin<dim_length>, metre>>; }; // quantity point used as Rep
requires !requires { typename quantity_kind<Width, metre, width<metre>>; }; // quantity kind used as Rep
requires !requires { typename quantity_kind<metre, Width, double>; }; // reordered arguments
requires !requires { typename quantity_kind<metre, double, Width>; }; // reordered arguments
@@ -454,7 +454,7 @@ concept invalid_compound_assignments = requires(quantity_kind<Width, metre, int>
requires invalid_compound_assignments_<Width, metre, length<metre, int>>;
requires invalid_compound_assignments_<Width, metre, height<metre, int>>;
requires invalid_compound_assignments_<Width, metre, horizontal_area<square_metre, int>>;
requires invalid_compound_assignments_<Width, metre, quantity_point<dim_length, metre, int>>;
requires invalid_compound_assignments_<Width, metre, quantity_point<dynamic_origin<dim_length>, metre, int>>;
requires invalid_compound_assignments_<Width, metre, std::chrono::seconds>;
};
static_assert(invalid_compound_assignments<width_kind>);
@@ -485,12 +485,12 @@ static_assert((width<metre, std::uint8_t>(0 * m) - width<metre, std::uint8_t>(1
static_assert(!std::is_invocable_v<std::plus<>, width<metre>, double>);
static_assert(!std::is_invocable_v<std::plus<>, width<metre>, length<metre>>);
static_assert(!std::is_invocable_v<std::plus<>, width<metre>, quantity_point<dim_length, metre>>);
static_assert(!std::is_invocable_v<std::plus<>, width<metre>, quantity_point<dynamic_origin<dim_length>, metre>>);
static_assert(!std::is_invocable_v<std::plus<>, width<metre>, height<metre>>);
static_assert(!std::is_invocable_v<std::plus<>, width<metre>, reference<dim_length, metre>>);
static_assert(!std::is_invocable_v<std::minus<>, width<metre>, double>);
static_assert(!std::is_invocable_v<std::minus<>, width<metre>, length<metre>>);
static_assert(!std::is_invocable_v<std::minus<>, width<metre>, quantity_point<dim_length, metre>>);
static_assert(!std::is_invocable_v<std::minus<>, width<metre>, quantity_point<dynamic_origin<dim_length>, metre>>);
static_assert(!std::is_invocable_v<std::minus<>, width<metre>, height<metre>>);
static_assert(!std::is_invocable_v<std::minus<>, width<metre>, reference<dim_length, metre>>);
@@ -650,17 +650,17 @@ static_assert(is_same_v<
static_assert(!std::is_invocable_v<std::multiplies<>, reference<dim_length, metre>, width<metre>>);
static_assert(!std::is_invocable_v<std::multiplies<>, width<metre>, height<metre>>);
static_assert(!std::is_invocable_v<std::multiplies<>, height<metre>, quantity_point<dim_length, metre>>);
static_assert(!std::is_invocable_v<std::multiplies<>, quantity_point<dim_length, metre>, height<metre>>);
static_assert(!std::is_invocable_v<std::multiplies<>, height<metre>, quantity_point<dynamic_origin<dim_length>, metre>>);
static_assert(!std::is_invocable_v<std::multiplies<>, quantity_point<dynamic_origin<dim_length>, metre>, height<metre>>);
static_assert(!std::is_invocable_v<std::divides<>, reference<dim_length, metre>, width<metre>>);
static_assert(!std::is_invocable_v<std::divides<>, width<metre>, height<metre>>);
static_assert(!std::is_invocable_v<std::divides<>, height<metre>, quantity_point<dim_length, metre>>);
static_assert(!std::is_invocable_v<std::divides<>, quantity_point<dim_length, metre>, height<metre>>);
static_assert(!std::is_invocable_v<std::divides<>, height<metre>, quantity_point<dynamic_origin<dim_length>, metre>>);
static_assert(!std::is_invocable_v<std::divides<>, quantity_point<dynamic_origin<dim_length>, metre>, height<metre>>);
static_assert(!std::is_invocable_v<std::modulus<>, width<metre, int>, reference<dim_length, metre>>);
static_assert(!std::is_invocable_v<std::modulus<>, width<metre, int>, length<metre, int>>);
static_assert(!std::is_invocable_v<std::modulus<>, width<metre, int>, quantity_point<dim_length, metre, int>>);
static_assert(!std::is_invocable_v<std::modulus<>, width<metre, int>, quantity_point<dynamic_origin<dim_length>, metre, int>>);
static_assert(!std::is_invocable_v<std::modulus<>, width<metre, int>, double>);
static_assert(!std::is_invocable_v<std::modulus<>, width<metre, int>, width<metre, double>>);
@@ -801,8 +801,8 @@ concept invalid_cast = requires {
requires !requires { quantity_kind_cast<dimensionless<one>>(quantity_kind<Width, metre, int>(1 * m)); };
requires !requires { quantity_kind_cast<square_metre>(quantity_kind<Width, metre, int>(1 * m)); };
requires !requires { quantity_kind_cast<second>(quantity_kind<Width, metre, int>(1 * m)); };
requires !requires { quantity_kind_cast<quantity_point<dim_length, metre, int>>(quantity_kind<Width, metre, int>(1 * m)); };
requires !requires { quantity_kind_cast<quantity_point<dim_one, one, int>>(quantity_kind<Width, metre, int>(1 * m)); };
requires !requires { quantity_kind_cast<quantity_point<dynamic_origin<dim_length>, metre, int>>(quantity_kind<Width, metre, int>(1 * m)); };
requires !requires { quantity_kind_cast<quantity_point<dynamic_origin<dim_one>, one, int>>(quantity_kind<Width, metre, int>(1 * m)); };
};
static_assert(invalid_cast<width_kind>);
@@ -57,6 +57,18 @@ struct cgs_height_kind : kind<cgs_height_kind, cgs::dim_length> {};
struct rate_of_climb_kind : derived_kind<rate_of_climb_kind, dim_speed, height_kind> {};
struct altitude_kind : point_kind<altitude_kind, cgs_height_kind> {};
struct sea_level_origin : point_origin<dim_length> {};
struct sea_level_altitude_kind : point_kind<sea_level_altitude_kind, height_kind, sea_level_origin> {};
template<Dimension D>
struct screen_origin : point_origin<D> {
template<Dimension D2>
using rebind = screen_origin<D2>;
};
struct screen_si_width_kind : point_kind<screen_si_width_kind, width_kind, screen_origin<dim_length>> {};
struct screen_si_cgs_width_kind :
point_kind<screen_si_cgs_width_kind, cgs_width_kind, screen_origin<cgs::dim_length>> {};
struct apple : kind<apple, dim_one> {};
struct orange : kind<orange, dim_one> {};
struct nth_apple_kind : point_kind<nth_apple_kind, apple> {};
@@ -65,6 +77,8 @@ struct nth_orange_kind : point_kind<nth_orange_kind, orange> {};
struct time_kind : kind<time_kind, dim_time> {};
struct time_point_kind : point_kind<time_point_kind, time_kind> {};
struct sys_time_point_kind : point_kind<time_point_kind, time_kind, clock_origin<std::chrono::system_clock>> {};
template <Unit U, Representation Rep = double> using width = quantity_kind<width_kind, U, Rep>;
template <Unit U, Representation Rep = double> using height = quantity_kind<height_kind, U, Rep>;
template <Unit U, Representation Rep = double> using abscissa = quantity_point_kind<abscissa_kind, U, Rep>;
@@ -76,6 +90,13 @@ template <Unit U, Representation Rep = double> using cgs_height = quantity_kind<
template <Unit U, Representation Rep = double> using rate_of_climb = quantity_kind<rate_of_climb_kind, U, Rep>;
template <Unit U, Representation Rep = double> using altitude = quantity_point_kind<altitude_kind, U, Rep>;
template<Unit U, Representation Rep = double>
using sea_level_altitude = quantity_point_kind<sea_level_altitude_kind, U, Rep>;
template<Unit U, Representation Rep = double>
using screen_si_width = quantity_point_kind<screen_si_width_kind, U, Rep>;
template<Unit U, Representation Rep = double>
using screen_si_cgs_width = quantity_point_kind<screen_si_cgs_width_kind, U, Rep>;
template <Unit U = one, Representation Rep = double> using apples = quantity_kind<apple, U, Rep>;
template <Unit U = one, Representation Rep = double> using oranges = quantity_kind<orange, U, Rep>;
template <Unit U = one, Representation Rep = double> using nth_apple = quantity_point_kind<nth_apple_kind, U, Rep>;
@@ -89,7 +110,7 @@ static_assert(QuantityPointKind<abscissa<metre>>);
static_assert(QuantityPointKind<nth_apple<one>>);
static_assert(!QuantityPointKind<double>);
static_assert(!QuantityPointKind<length<metre>>);
static_assert(!QuantityPointKind<quantity_point<dim_length, metre>>);
static_assert(!QuantityPointKind<quantity_point<dynamic_origin<dim_length>, metre>>);
static_assert(!QuantityPointKind<width<metre>>);
static_assert(QuantityPointKindOf<abscissa<metre>, abscissa_kind>);
@@ -100,9 +121,12 @@ static_assert(!QuantityPointKindOf<length<metre>, metre>);
static_assert(!QuantityPointKindOf<width<metre>, abscissa_kind>);
static_assert(!QuantityPointKindOf<width<metre>, width_kind>);
static_assert(!QuantityPointKindOf<width<metre>, metre>);
static_assert(!QuantityPointKindOf<quantity_point<dim_length, metre>, width_kind>);
static_assert(!QuantityPointKindOf<quantity_point<dim_length, metre>, dim_length>);
static_assert(!QuantityPointKindOf<quantity_point<dim_length, metre>, metre>);
static_assert(!QuantityPointKindOf<abscissa<metre>, sea_level_altitude_kind>);
static_assert(!QuantityPointKindOf<altitude<metre>, sea_level_altitude_kind>);
static_assert(!QuantityPointKindOf<quantity_point<dynamic_origin<dim_length>, metre>, width_kind>);
static_assert(!QuantityPointKindOf<quantity_point<dynamic_origin<dim_length>, metre>, dim_length>);
static_assert(!QuantityPointKindOf<quantity_point<dynamic_origin<dim_length>, metre>, dynamic_origin<dim_length>>);
static_assert(!QuantityPointKindOf<quantity_point<dynamic_origin<dim_length>, metre>, metre>);
///////////////
@@ -117,7 +141,7 @@ concept invalid_types = requires {
requires !requires { typename quantity_point_kind<Width, metre, int>; }; // width_kind is not a point kind
requires !requires { typename quantity_point_kind<Abscissa, second, int>; }; // unit of a different dimension
requires !requires { typename quantity_point_kind<Abscissa, metre, length<metre>>; }; // quantity used as Rep
requires !requires { typename quantity_point_kind<Abscissa, metre, quantity_point<dim_length, metre>>; }; // quantity point used as Rep
requires !requires { typename quantity_point_kind<Abscissa, metre, quantity_point<dynamic_origin<dim_length>, metre>>; }; // quantity point used as Rep
requires !requires { typename quantity_point_kind<Abscissa, metre, width<metre>>; }; // quantity kind used as Rep
requires !requires { typename quantity_point_kind<Abscissa, metre, abscissa<metre>>; }; // quantity point kind used as Rep
requires !requires { typename quantity_point_kind<metre, Abscissa, double>; }; // reordered arguments
@@ -160,6 +184,7 @@ static_assert(!std::is_aggregate_v<abscissa<metre>>);
static_assert(is_same_v<abscissa<metre>::point_kind_type, abscissa_kind>);
static_assert(is_same_v<abscissa<metre>::kind_type, width_kind>);
static_assert(is_same_v<abscissa<metre>::origin, dynamic_origin<dim_length>>);
static_assert(is_same_v<abscissa<metre>::quantity_kind_type, width<metre>>);
static_assert(is_same_v<abscissa<metre>::quantity_type, length<metre>>);
static_assert(is_same_v<abscissa<metre>::dimension, dim_length>);
@@ -287,6 +312,14 @@ static_assert(!constructible_or_convertible_from<abscissa<metre, int>>(quantity_
static_assert(!constructible_or_convertible_from<abscissa<metre, double>>(quantity_point(1.0 * (m * m))));
static_assert(!constructible_or_convertible_from<abscissa<metre, double>>(quantity_point(1.0 * s)));
static_assert(construct_from_only<screen_si_width<metre>>(quantity_point<screen_origin<dim_length>, metre>(1 * m))
.relative()
.common() == 1 * m);
static_assert(construct_from_only<screen_si_width<metre>>(quantity_point<screen_origin<cgs::dim_length>, metre>(1 * m))
.relative()
.common() == 1 * m);
static_assert(!constructible_or_convertible_from<sea_level_altitude<metre, double>>(quantity_point(1.0 * m)));
// clang-format off
static_assert(construct_from_only<nth_apple<one, short>>(quantity_point(1)).relative().common() == 1);
static_assert(construct_from_only<nth_apple<one, int>>(quantity_point(1)).relative().common() == 1);
@@ -303,8 +336,12 @@ static_assert(!constructible_or_convertible_from<nth_apple<one, int>>(quantity_p
static_assert(!constructible_or_convertible_from<nth_apple<one, int>>(quantity_point(dimensionless<percent, double>(1))));
static_assert(!constructible_or_convertible_from<nth_apple<one, double>>(quantity_point(1.0 * s)));
static_assert(construct_from_only<quantity_point_kind<time_point_kind, second, int>>(sys_seconds{42s}).relative().common() == 42 * s);
// clang-format on
static_assert(
construct_from_only<quantity_point_kind<sys_time_point_kind, second, int>>(sys_seconds{42s}).relative().common() ==
42 * s);
static_assert(!constructible_or_convertible_from<quantity_point_kind<time_point_kind, second, int>>(sys_seconds{42s}),
"no implicit conversion to/from dynamic_origin");
//////////////////////////////////////
@@ -365,6 +402,15 @@ static_assert(!constructible_or_convertible_from<nth_apple<one, int>>(nth_orange
static_assert(!constructible_or_convertible_from<nth_apple<one, int>>(abscissa<metre, int>(1 * m)));
// clang-format on
static_assert(!constructible_or_convertible_from<quantity_point_kind<sys_time_point_kind, second, int>>(
quantity_point_kind<time_point_kind, second, int>{}),
"no implicit conversion to/from dynamic_origin");
static_assert(!constructible_or_convertible_from<quantity_point_kind<time_point_kind, second, int>>(
quantity_point_kind<sys_time_point_kind, second, int>{}),
"no implicit conversion to/from dynamic_origin");
static_assert(!constructible_or_convertible_from<screen_si_width<metre>>(screen_si_cgs_width<metre>(1 * m)),
"base kinds are not the same (required by equivalent<Kind, Kind>)");
//////////////////////
// other conversions
@@ -375,7 +421,7 @@ static_assert(!std::is_convertible_v<abscissa<metre, int>, dimensionless<one, in
static_assert(!std::is_convertible_v<abscissa<metre, int>, length<metre, int>>);
static_assert(!std::is_convertible_v<abscissa<metre, int>, width<metre, int>>);
static_assert(!std::is_convertible_v<abscissa<metre, int>, height<metre, int>>);
static_assert(!std::is_convertible_v<abscissa<metre, int>, quantity_point<dim_length, metre, int>>);
static_assert(!std::is_convertible_v<abscissa<metre, int>, quantity_point<dynamic_origin<dim_length>, metre, int>>);
////////////////////////
@@ -420,7 +466,7 @@ concept invalid_compound_assignments = requires(quantity_point_kind<Abscissa, me
requires invalid_compound_assignments_<Abscissa, metre, length<metre, int>>;
requires invalid_compound_assignments_<Abscissa, metre, height<metre, int>>;
requires invalid_compound_assignments_<Abscissa, metre, rate_of_climb<metre_per_second, int>>;
requires invalid_compound_assignments_<Abscissa, metre, quantity_point<dim_length, metre, int>>;
requires invalid_compound_assignments_<Abscissa, metre, quantity_point<dynamic_origin<dim_length>, metre, int>>;
requires invalid_compound_assignments_<Abscissa, metre, std::chrono::seconds>;
};
static_assert(invalid_compound_assignments<abscissa_kind>);
@@ -447,13 +493,13 @@ static_assert(same(width<kilometre, int>(2 * km) + abscissa<metre, double>(3e3 *
static_assert(same(width<metre, double>(2e3 * m) + abscissa<kilometre, int>(3 * km), abscissa<metre, double>(5e3 * m)));
static_assert(!std::is_invocable_v<std::plus<>, abscissa<metre>, double>);
static_assert(!std::is_invocable_v<std::plus<>, abscissa<metre>, length<metre>>);
static_assert(!std::is_invocable_v<std::plus<>, abscissa<metre>, quantity_point<dim_length, metre>>);
static_assert(!std::is_invocable_v<std::plus<>, abscissa<metre>, quantity_point<dynamic_origin<dim_length>, metre>>);
static_assert(!std::is_invocable_v<std::plus<>, abscissa<metre>, height<metre>>);
static_assert(!std::is_invocable_v<std::plus<>, abscissa<metre>, abscissa<metre>>);
static_assert(!std::is_invocable_v<std::plus<>, abscissa<metre>, abscissa<kilometre>>);
static_assert(!std::is_invocable_v<std::plus<>, abscissa<kilometre>, abscissa<metre>>);
static_assert(!std::is_invocable_v<std::plus<>, height<metre>, abscissa<metre>>);
static_assert(!std::is_invocable_v<std::plus<>, quantity_point<dim_length, metre>, abscissa<metre>>);
static_assert(!std::is_invocable_v<std::plus<>, quantity_point<dynamic_origin<dim_length>, metre>, abscissa<metre>>);
static_assert(!std::is_invocable_v<std::plus<>, length<metre>, abscissa<metre>>);
static_assert(!std::is_invocable_v<std::plus<>, double, abscissa<metre>>);
@@ -469,14 +515,15 @@ static_assert(same(abscissa<kilometre, int>(2 * km) - abscissa<metre, double>(3e
static_assert(same(abscissa<metre, double>(2e3 * m) - abscissa<kilometre, int>(3 * km), width<metre, double>(-1e3 * m)));
static_assert(!std::is_invocable_v<std::minus<>, abscissa<metre>, double>);
static_assert(!std::is_invocable_v<std::minus<>, abscissa<metre>, length<metre>>);
static_assert(!std::is_invocable_v<std::minus<>, abscissa<metre>, quantity_point<dim_length, metre>>);
static_assert(!std::is_invocable_v<std::minus<>, abscissa<metre>, quantity_point<dynamic_origin<dim_length>, metre>>);
static_assert(!std::is_invocable_v<std::minus<>, abscissa<metre>, height<metre>>);
static_assert(!std::is_invocable_v<std::minus<>, abscissa<metre>, ordinate<metre>>);
static_assert(!std::is_invocable_v<std::minus<>, ordinate<metre>, abscissa<metre>>);
static_assert(!std::is_invocable_v<std::minus<>, height<metre>, abscissa<metre>>);
static_assert(!std::is_invocable_v<std::minus<>, quantity_point<dim_length, metre>, abscissa<metre>>);
static_assert(!std::is_invocable_v<std::minus<>, quantity_point<dynamic_origin<dim_length>, metre>, abscissa<metre>>);
static_assert(!std::is_invocable_v<std::minus<>, length<metre>, abscissa<metre>>);
static_assert(!std::is_invocable_v<std::minus<>, double, abscissa<metre>>);
static_assert(!std::is_invocable_v<std::minus<>, screen_si_width<metre>, screen_si_cgs_width<metre>>);
// clang-format on
@@ -496,8 +543,8 @@ static_assert(std::equality_comparable_with<abscissa<nanometre, int>, abscissa<k
static_assert(std::equality_comparable_with<abscissa<cgs::centimetre, int>, abscissa<millimetre, double>>);
static_assert(std::equality_comparable_with<abscissa<metre>, abscissa<cgs::centimetre>>);
// clang-format on
template<typename Abscissa>
concept invalid_equality = requires(quantity_point_kind<Abscissa, metre, int> x) {
template<typename Int>
concept invalid_equality = requires(quantity_point_kind<abscissa_kind, metre, Int> x, Int i) {
requires !requires { x == 1; };
requires !requires { x != 1.0; };
requires !requires { x == 1 * m; };
@@ -516,8 +563,9 @@ concept invalid_equality = requires(quantity_point_kind<Abscissa, metre, int> x)
requires !requires { x == quantity_point(dimensionless<percent>(1.0)); };
requires !requires { x != quantity_point_kind(cgs_width<metre, int>(1 * m)); };
requires !requires { x == ordinate<metre, int>(1 * m); };
requires !requires { screen_si_width<metre, Int>{} != screen_si_cgs_width<metre, Int>{}; };
};
static_assert(invalid_equality<abscissa_kind>);
static_assert(invalid_equality<int>);
// clang-format off
static_assert(abscissa<metre, int>(1 * m) < abscissa<metre, int>(2 * m));
@@ -531,8 +579,8 @@ static_assert(std::three_way_comparable_with<abscissa<nanometre, int>, abscissa<
static_assert(std::three_way_comparable_with<abscissa<cgs::centimetre, int>, abscissa<millimetre, double>>);
static_assert(std::three_way_comparable_with<abscissa<metre>, abscissa<cgs::centimetre>>);
// clang-format on
template<typename Abscissa>
concept invalid_relational = requires(quantity_point_kind<Abscissa, metre, int> x) {
template<typename Int>
concept invalid_relational = requires(quantity_point_kind<abscissa_kind, metre, Int> x, Int i) {
requires !requires { x < 1; };
requires !requires { x <= 1.0; };
requires !requires { x >= 1 * m; };
@@ -551,8 +599,9 @@ concept invalid_relational = requires(quantity_point_kind<Abscissa, metre, int>
requires !requires { x < quantity_point(dimensionless<percent>(1.0)); };
requires !requires { x <= quantity_point_kind(cgs_width<metre, int>(1 * m)); };
requires !requires { x >= ordinate<metre, int>(1 * m); };
requires !requires { screen_si_width<metre, Int>{} > screen_si_cgs_width<metre, Int>{}; };
};
static_assert(invalid_relational<abscissa_kind>);
static_assert(invalid_relational<int>);
/////////////////////////////
@@ -600,6 +649,7 @@ static_assert(same(quantity_point_kind_cast<length<kilometre, int>>(abscissa<met
static_assert(same(quantity_point_kind_cast<length<centimetre, int>>(abscissa<metre, int>(1 * m)), abscissa<centimetre, int>(100 * cm)));
static_assert(same(quantity_point_kind_cast<length<centimetre, int>>(abscissa<metre, double>(0.01 * m)), abscissa<centimetre, int>(1 * cm)));
static_assert(same(quantity_point_kind_cast<length<centimetre, int>>(abscissa<cgs::centimetre, int>(1 * cgs_cm)), abscissa<cgs::centimetre, int>(1 * cgs_cm)));
static_assert(same(quantity_point_kind_cast<screen_si_cgs_width<metre, int>>(screen_si_width<metre, int>(1 * m)), screen_si_cgs_width<metre, int>(1 * m)));
// clang-format on
template<typename Int>
concept invalid_cast = requires(Int i) {
@@ -617,8 +667,9 @@ concept invalid_cast = requires(Int i) {
requires !requires { quantity_point_kind_cast<dimensionless<one>>(abscissa<metre, Int>(i * m)); };
requires !requires { quantity_point_kind_cast<square_metre>(abscissa<metre, Int>(i * m)); };
requires !requires { quantity_point_kind_cast<second>(abscissa<metre, Int>(i * m)); };
requires !requires { quantity_point_kind_cast<quantity_point<dim_length, metre, Int>>(abscissa<metre, Int>(i * m)); };
requires !requires { quantity_point_kind_cast<quantity_point<dim_one, one, Int>>(abscissa<metre, Int>(i * m)); };
requires !requires { quantity_point_kind_cast<quantity_point<dynamic_origin<dim_length>, metre, Int>>(abscissa<metre, Int>(i * m)); };
requires !requires { quantity_point_kind_cast<quantity_point<dynamic_origin<dim_one>, one, Int>>(abscissa<metre, Int>(i * m)); };
requires !requires { quantity_point_kind_cast<quantity_point<dynamic_origin<dim_length>, metre, Int>>(screen_si_width<metre, Int>(i * m)); };
};
static_assert(invalid_cast<int>);
+107 -68
View File
@@ -41,72 +41,89 @@ using namespace references;
using namespace std::chrono_literals;
using sys_seconds = std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>;
struct sea_level_origin : point_origin<dim_length> {};
// class invariants
template<typename DimLength>
concept invalid_types = requires
{
requires !requires { typename quantity_point<DimLength, second, int>; }; // unit of a different dimension
requires !requires { typename quantity_point<DimLength, metre, quantity<DimLength, metre, int>>; }; // quantity used as Rep
// quantity point used as Rep
requires !requires { typename quantity_point<DimLength, metre, quantity_point<DimLength, metre, int>>; };
requires !requires { typename quantity<metre, DimLength, double>; }; // reordered arguments
// unit of a different dimension:
requires !requires { typename quantity_point<dynamic_origin<DimLength>, second, int>; };
// quantity used as Rep:
requires !requires { typename quantity_point<dynamic_origin<DimLength>, metre, quantity<DimLength, metre, int>>; };
// quantity point used as Rep:
requires !requires { typename quantity_point<dynamic_origin<DimLength>, metre,
quantity_point<dynamic_origin<DimLength>, metre, int>>; };
// reordered arguments:
requires !requires { typename quantity_point<metre, dynamic_origin<DimLength>, double>; };
// dimension used as origin:
requires !requires { typename quantity_point<DimLength, second, int>; };
};
static_assert(invalid_types<dim_length>);
// member types
static_assert(is_same_v<quantity_point<dim_length, metre, int>::rep, int>);
static_assert(is_same_v<quantity_point<dim_length, metre, double>::rep, double>);
static_assert(is_same_v<quantity_point<dim_length, metre, int>::unit, metre>);
static_assert(is_same_v<quantity_point<dim_length, kilometre, int>::unit, kilometre>);
static_assert(is_same_v<quantity_point<dim_length, metre, int>::dimension, dim_length>);
static_assert(is_same_v<quantity_point<dim_length, metre, int>::quantity_type, quantity<dim_length, metre, int>>);
static_assert(is_same_v<quantity_point<dynamic_origin<dim_length>, metre, int>::rep, int>);
static_assert(is_same_v<quantity_point<dynamic_origin<dim_length>, metre, double>::rep, double>);
static_assert(is_same_v<quantity_point<dynamic_origin<dim_length>, metre, int>::unit, metre>);
static_assert(is_same_v<quantity_point<dynamic_origin<dim_length>, kilometre, int>::unit, kilometre>);
static_assert(is_same_v<quantity_point<dynamic_origin<dim_length>, metre, int>::dimension, dim_length>);
static_assert(is_same_v<quantity_point<dynamic_origin<dim_length>, metre, int>::origin, dynamic_origin<dim_length>>);
static_assert(is_same_v<quantity_point<dynamic_origin<dim_length>, metre, int>::quantity_type, quantity<dim_length, metre, int>>);
// constructors
static_assert(quantity_point(1).relative() == quantity(1));
static_assert(!std::is_convertible_v<int, quantity_point<dim_one, one, int>>);
static_assert(!std::is_convertible_v<int, quantity_point<dynamic_origin<dim_one>, one, int>>);
static_assert(quantity_point(42s).relative() == 42 * s);
static_assert(quantity_point(sys_seconds{42s}).relative() == 42 * s);
static_assert(!std::is_convertible_v<std::chrono::seconds, quantity_point<dim_time, second, std::chrono::seconds::rep>>);
static_assert(!std::is_convertible_v<sys_seconds, quantity_point<dim_time, second, sys_seconds::rep>>);
static_assert(!std::is_convertible_v<std::chrono::seconds, quantity_point<dynamic_origin<dim_time>, second, std::chrono::seconds::rep>>);
static_assert(!std::is_convertible_v<std::chrono::seconds, quantity_point<clock_origin<std::chrono::system_clock>, second, std::chrono::seconds::rep>>);
static_assert(!std::is_convertible_v<sys_seconds, quantity_point<dynamic_origin<dim_time>, second, sys_seconds::rep>>);
static_assert(!std::is_convertible_v<sys_seconds, quantity_point<clock_origin<std::chrono::system_clock>, second, sys_seconds::rep>>);
static_assert(quantity_point<dim_length, metre, int>().relative() == 0_q_m);
constexpr quantity_point<dim_length, metre, int> km{1000_q_m};
static_assert(quantity_point<dynamic_origin<dim_length>, metre, int>().relative() == 0_q_m);
constexpr quantity_point<dynamic_origin<dim_length>, metre, int> km{1000_q_m};
static_assert(km.relative() == 1000_q_m);
static_assert(quantity_point<dim_length, metre, int>(km).relative() == km.relative());
static_assert(quantity_point<dynamic_origin<dim_length>, metre, int>(km).relative() == km.relative());
static_assert(quantity_point<dim_length, metre, int>(1_q_m).relative() == 1_q_m);
static_assert(!std::is_constructible_v<quantity_point<dim_length, metre, int>, double>); // truncating conversion
static_assert(quantity_point<dim_length, metre, double>(1.0_q_m).relative() == 1.0_q_m);
static_assert(quantity_point<dim_length, metre, double>(1_q_m).relative() == 1_q_m);
static_assert(quantity_point<dim_length, metre, long double>(3.14_q_m).relative() == 3.14_q_m);
static_assert(quantity_point<dynamic_origin<dim_length>, metre, int>(1_q_m).relative() == 1_q_m);
static_assert(!std::is_constructible_v<quantity_point<dynamic_origin<dim_length>, metre, int>, double>); // truncating conversion
static_assert(quantity_point<dynamic_origin<dim_length>, metre, double>(1.0_q_m).relative() == 1.0_q_m);
static_assert(quantity_point<dynamic_origin<dim_length>, metre, double>(1_q_m).relative() == 1_q_m);
static_assert(quantity_point<dynamic_origin<dim_length>, metre, long double>(3.14_q_m).relative() == 3.14_q_m);
static_assert(quantity_point<dim_length, metre, int>(km).relative() == 1000_q_m);
static_assert(!std::is_constructible_v<quantity_point<dim_length, metre, int>,
quantity_point<dim_length, metre, double>>); // truncating conversion
static_assert(quantity_point<dim_length, metre, double>(quantity_point(1000.0_q_m)).relative() == 1000.0_q_m);
static_assert(quantity_point<dim_length, metre, double>(km).relative() == 1000.0_q_m);
static_assert(quantity_point<dim_length, metre, int>(quantity_point(1_q_km)).relative() == 1000_q_m);
static_assert(!std::is_constructible_v<quantity_point<dim_length, metre, int>,
quantity_point<dim_time, second, int>>); // different dimensions
static_assert(!std::is_constructible_v<quantity_point<dim_length, kilometre, int>,
quantity_point<dim_length, metre, int>>); // truncating conversion
static_assert(quantity_point<dynamic_origin<dim_length>, metre, int>(km).relative() == 1000_q_m);
static_assert(!std::is_constructible_v<quantity_point<dynamic_origin<dim_length>, metre, int>,
quantity_point<dynamic_origin<dim_length>, metre, double>>); // truncating conversion
static_assert(quantity_point<dynamic_origin<dim_length>, metre, double>(quantity_point(1000.0_q_m)).relative() == 1000.0_q_m);
static_assert(quantity_point<dynamic_origin<dim_length>, metre, double>(km).relative() == 1000.0_q_m);
static_assert(quantity_point<dynamic_origin<dim_length>, metre, int>(quantity_point(1_q_km)).relative() == 1000_q_m);
static_assert(!std::is_constructible_v<quantity_point<dynamic_origin<dim_length>, metre, int>,
quantity_point<dynamic_origin<dim_time>, second, int>>); // different dimensions
static_assert(!std::is_constructible_v<quantity_point<dynamic_origin<dim_length>, kilometre, int>,
quantity_point<dynamic_origin<dim_length>, metre, int>>); // truncating conversion
static_assert(!std::is_constructible_v<quantity_point<sea_level_origin, kilometre, int>,
quantity_point<dynamic_origin<dim_length>, metre, int>>,
"non-equivalent origins");
static_assert(!std::is_constructible_v<quantity_point<dynamic_origin<dim_time>, second, int>, sys_seconds>,
"non-equivalent origins, no implicit conversion from `clock_origin`");
// assignment operator
static_assert([]() { quantity_point<dim_length, metre, int> l1(1_q_m), l2{}; return l2 = l1; }().relative() == 1_q_m);
static_assert([]() { quantity_point<dynamic_origin<dim_length>, metre, int> l1(1_q_m), l2{}; return l2 = l1; }().relative() == 1_q_m);
// static member functions
static_assert(quantity_point<dim_length, metre, int>::min().relative().number() == std::numeric_limits<int>::lowest());
static_assert(quantity_point<dim_length, metre, int>::max().relative().number() == std::numeric_limits<int>::max());
static_assert(quantity_point<dim_length, metre, double>::min().relative().number() ==
static_assert(quantity_point<dynamic_origin<dim_length>, metre, int>::min().relative().number() == std::numeric_limits<int>::lowest());
static_assert(quantity_point<dynamic_origin<dim_length>, metre, int>::max().relative().number() == std::numeric_limits<int>::max());
static_assert(quantity_point<dynamic_origin<dim_length>, metre, double>::min().relative().number() ==
std::numeric_limits<double>::lowest());
static_assert(quantity_point<dim_length, metre, double>::max().relative().number() ==
static_assert(quantity_point<dynamic_origin<dim_length>, metre, double>::max().relative().number() ==
std::numeric_limits<double>::max());
// unary member operators
@@ -114,19 +131,19 @@ static_assert(quantity_point<dim_length, metre, double>::max().relative().number
static_assert([](auto v) {
auto vv = v++;
return std::pair(v, vv);
}(km) == std::pair(quantity_point<dim_length, metre, int>(1001_q_m), quantity_point<dim_length, metre, int>(1000_q_m)));
}(km) == std::pair(quantity_point<dynamic_origin<dim_length>, metre, int>(1001_q_m), quantity_point<dynamic_origin<dim_length>, metre, int>(1000_q_m)));
static_assert([](auto v) {
auto vv = ++v;
return std::pair(v, vv);
}(km) == std::pair(quantity_point<dim_length, metre, int>(1001_q_m), quantity_point<dim_length, metre, int>(1001_q_m)));
}(km) == std::pair(quantity_point<dynamic_origin<dim_length>, metre, int>(1001_q_m), quantity_point<dynamic_origin<dim_length>, metre, int>(1001_q_m)));
static_assert([](auto v) {
auto vv = v--;
return std::pair(v, vv);
}(km) == std::pair(quantity_point<dim_length, metre, int>(999_q_m), quantity_point<dim_length, metre, int>(1000_q_m)));
}(km) == std::pair(quantity_point<dynamic_origin<dim_length>, metre, int>(999_q_m), quantity_point<dynamic_origin<dim_length>, metre, int>(1000_q_m)));
static_assert([](auto v) {
auto vv = --v;
return std::pair(v, vv);
}(km) == std::pair(quantity_point<dim_length, metre, int>(999_q_m), quantity_point<dim_length, metre, int>(999_q_m)));
}(km) == std::pair(quantity_point<dynamic_origin<dim_length>, metre, int>(999_q_m), quantity_point<dynamic_origin<dim_length>, metre, int>(999_q_m)));
// compound assignment
@@ -135,23 +152,23 @@ static_assert((quantity_point(2_q_m) -= 1_q_m).relative().number() == 1);
// non-member arithmetic operators
static_assert(compare<decltype(quantity_point<dim_length, metre, int>() + length<metre, double>()),
quantity_point<dim_length, metre, double>>);
static_assert(compare<decltype(length<metre, int>() + quantity_point<dim_length, metre, double>()),
quantity_point<dim_length, metre, double>>);
static_assert(compare<decltype(quantity_point<dim_length, kilometre, int>() + length<metre, double>()),
quantity_point<dim_length, metre, double>>);
static_assert(compare<decltype(length<kilometre, int>() + quantity_point<dim_length, metre, double>()),
quantity_point<dim_length, metre, double>>);
static_assert(compare<decltype(quantity_point<dim_length, metre, double>() - length<metre, int>()),
quantity_point<dim_length, metre, double>>);
static_assert(compare<decltype(quantity_point<dim_length, kilometre, double>() - length<metre, int>()),
quantity_point<dim_length, metre, double>>);
static_assert(compare<decltype(quantity_point<dynamic_origin<dim_length>, metre, int>() + length<metre, double>()),
quantity_point<dynamic_origin<dim_length>, metre, double>>);
static_assert(compare<decltype(length<metre, int>() + quantity_point<dynamic_origin<dim_length>, metre, double>()),
quantity_point<dynamic_origin<dim_length>, metre, double>>);
static_assert(compare<decltype(quantity_point<dynamic_origin<dim_length>, kilometre, int>() + length<metre, double>()),
quantity_point<dynamic_origin<dim_length>, metre, double>>);
static_assert(compare<decltype(length<kilometre, int>() + quantity_point<dynamic_origin<dim_length>, metre, double>()),
quantity_point<dynamic_origin<dim_length>, metre, double>>);
static_assert(compare<decltype(quantity_point<dynamic_origin<dim_length>, metre, double>() - length<metre, int>()),
quantity_point<dynamic_origin<dim_length>, metre, double>>);
static_assert(compare<decltype(quantity_point<dynamic_origin<dim_length>, kilometre, double>() - length<metre, int>()),
quantity_point<dynamic_origin<dim_length>, metre, double>>);
static_assert(
compare<decltype(quantity_point<dim_length, metre, double>() - quantity_point<dim_length, metre, int>()),
compare<decltype(quantity_point<dynamic_origin<dim_length>, metre, double>() - quantity_point<dynamic_origin<dim_length>, metre, int>()),
length<metre, double>>);
static_assert(
compare<decltype(quantity_point<dim_length, kilometre, double>() - quantity_point<dim_length, metre, int>()),
compare<decltype(quantity_point<dynamic_origin<dim_length>, kilometre, double>() - quantity_point<dynamic_origin<dim_length>, metre, int>()),
length<metre, double>>);
static_assert((1_q_m + km).relative().number() == 1001);
@@ -159,6 +176,13 @@ static_assert((quantity_point(1_q_m) + 1_q_km).relative().number() == 1001);
static_assert((km - 1_q_m).relative().number() == 999);
static_assert((quantity_point(1_q_km) - quantity_point(1_q_m)).number() == 999);
template<typename Int>
concept invalid_subtraction = requires(quantity_point<dynamic_origin<dim_length>, metre, Int> lhs,
quantity_point<sea_level_origin, metre, Int> rhs) {
requires !requires { rhs - lhs; };
};
static_assert(invalid_subtraction<int>);
// comparators
static_assert(quantity_point(2_q_m) + 1_q_m == quantity_point(3_q_m));
@@ -190,6 +214,14 @@ static_assert(quantity_point(999_q_m) < quantity_point(1_q_km));
static_assert(quantity_point(1000_q_m) >= quantity_point(1_q_km));
static_assert(quantity_point(1000_q_m) <= quantity_point(1_q_km));
template<typename Int>
concept invalid_comparisons = requires(quantity_point<dynamic_origin<dim_length>, metre, Int> lhs,
quantity_point<sea_level_origin, metre, Int> rhs) {
requires !requires { lhs == rhs; };
requires !requires { lhs < rhs; };
};
static_assert(invalid_comparisons<int>);
// alias units
static_assert(quantity_point(2_q_l) + 2_q_ml == quantity_point(2002_q_ml));
@@ -199,19 +231,19 @@ static_assert(2_q_dm3 + quantity_point(2_q_cm3) == quantity_point(2002_q_ml));
// is_quantity_point
static_assert(QuantityPoint<quantity_point<dim_length, millimetre, int>>);
static_assert(QuantityPoint<quantity_point<dynamic_origin<dim_length>, millimetre, int>>);
// common_quantity_point
static_assert(compare<
common_quantity_point<quantity_point<dim_length, metre, int>, quantity_point<dim_length, kilometre, int>>,
quantity_point<dim_length, metre, int>>);
static_assert(compare<common_quantity_point<quantity_point<dim_length, kilometre, long long>,
quantity_point<dim_length, metre, int>>,
quantity_point<dim_length, metre, long long>>);
static_assert(compare<common_quantity_point<quantity_point<dim_length, kilometre, long long>,
quantity_point<dim_length, millimetre, double>>,
quantity_point<dim_length, millimetre, double>>);
common_quantity_point<quantity_point<dynamic_origin<dim_length>, metre, int>, quantity_point<dynamic_origin<dim_length>, kilometre, int>>,
quantity_point<dynamic_origin<dim_length>, metre, int>>);
static_assert(compare<common_quantity_point<quantity_point<dynamic_origin<dim_length>, kilometre, long long>,
quantity_point<dynamic_origin<dim_length>, metre, int>>,
quantity_point<dynamic_origin<dim_length>, metre, long long>>);
static_assert(compare<common_quantity_point<quantity_point<dynamic_origin<dim_length>, kilometre, long long>,
quantity_point<dynamic_origin<dim_length>, millimetre, double>>,
quantity_point<dynamic_origin<dim_length>, millimetre, double>>);
// common_type
@@ -224,11 +256,11 @@ static_assert(std::equality_comparable_with<decltype(quantity_point(1_q_m)), dec
// quantity_cast
static_assert(quantity_point_cast<quantity_point<dim_length, metre, int>>(quantity_point(2_q_km)).relative().number() ==
static_assert(quantity_point_cast<quantity_point<dynamic_origin<dim_length>, metre, int>>(quantity_point(2_q_km)).relative().number() ==
2000);
static_assert(
quantity_point_cast<quantity_point<dim_length, kilometre, int>>(quantity_point(2000_q_m)).relative().number() == 2);
static_assert(quantity_point_cast<quantity_point<dim_length, metre, int>>(quantity_point(1.23_q_m)).relative().number() ==
quantity_point_cast<quantity_point<dynamic_origin<dim_length>, kilometre, int>>(quantity_point(2000_q_m)).relative().number() == 2);
static_assert(quantity_point_cast<quantity_point<dynamic_origin<dim_length>, metre, int>>(quantity_point(1.23_q_m)).relative().number() ==
1);
static_assert(quantity_point_cast<length<metre, int>>(quantity_point(2_q_km)).relative().number() == 2000);
static_assert(quantity_point_cast<length<kilometre, int>>(quantity_point(2000_q_m)).relative().number() == 2);
@@ -238,6 +270,13 @@ static_assert(quantity_point_cast<kilometre>(quantity_point(2000_q_m)).relative(
static_assert(quantity_point_cast<int>(quantity_point(1.23_q_m)).relative().number() == 1);
static_assert(quantity_point_cast<dim_speed, kilometre_per_hour>(quantity_point(2000.0_q_m / 3600.0_q_s)).relative().number() == 2);
template<typename Int>
concept invalid_cast = requires(Int i) {
requires !requires { quantity_point_cast<quantity_point<dynamic_origin<dim_time>, second, Int>>(quantity_point(i * m)); };
requires !requires { quantity_point_cast<quantity_point<dynamic_origin<dim_length>, metre, Int>>(quantity_point<sea_level_origin, metre, Int>(i * m)); };
};
static_assert(invalid_cast<int>);
// time
static_assert(quantity_point{1_q_h} == quantity_point{3600_q_s});
@@ -263,6 +302,6 @@ concept dimensional_analysis = requires(T t)
pow<2>(t);
};
static_assert(!dimensional_analysis<quantity_point<dim_length, metre, int>>);
static_assert(!dimensional_analysis<quantity_point<dynamic_origin<dim_length>, metre, int>>);
} // namespace