2018-08-22 12:11:19 +02:00
// 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.
2020-09-10 11:33:58 +02:00
#include "test_tools.h"
2019-09-24 16:59:45 +02:00
#include "units/math.h"
2020-10-06 18:17:52 +02:00
#include "units/physical/si/cgs/derived/speed.h"
#include "units/physical/si/derived/area.h"
#include "units/physical/si/derived/frequency.h"
#include "units/physical/si/derived/speed.h"
#include "units/physical/si/derived/volume.h"
#include "units/physical/si/fps/derived/speed.h"
2018-09-28 10:53:21 -07:00
#include <chrono>
2020-10-06 18:17:52 +02:00
#include <complex>
#include <mutex>
#include <string>
2019-12-04 17:46:19 +01:00
#include <utility>
2018-10-19 13:02:58 +02:00
2018-09-28 07:47:37 -07:00
namespace {
2018-08-22 12:11:19 +02:00
2019-12-04 17:46:19 +01:00
using namespace units ;
2020-05-08 22:39:24 +02:00
using namespace units :: physical :: si ;
2018-09-28 07:47:37 -07:00
2020-10-06 18:17:52 +02:00
//////////////////////////////
// quantity class invariants
//////////////////////////////
static_assert ( sizeof ( length < metre > ) == sizeof ( double ));
static_assert ( sizeof ( length < metre , short > ) == sizeof ( short ));
#if COMP_GCC != 10 || COMP_GCC_MINOR != 2 // TODO remove when gcc 10.3 releases
template < template < typename , typename , typename > typename Q >
concept invalid_types = requires {
requires ! requires { typename Q < dim_length , second , int > ; }; // unit of a different dimension
requires ! requires { typename Q < dim_length , metre , length < metre >> ; }; // quantity used as Rep
requires ! requires { typename Q < metre , dim_length , double > ; }; // reordered arguments
requires ! requires { typename Q < metre , double , dim_length > ; }; // reordered arguments
2020-09-05 21:41:02 -04:00
};
2020-10-06 18:17:52 +02:00
static_assert ( invalid_types < quantity > );
#endif
2020-09-05 21:41:02 -04:00
2020-10-06 18:17:52 +02:00
static_assert ( std :: is_trivially_default_constructible_v < length < metre >> );
static_assert ( std :: is_trivially_copy_constructible_v < length < metre >> );
static_assert ( std :: is_trivially_move_constructible_v < length < metre >> );
static_assert ( std :: is_trivially_copy_assignable_v < length < metre >> );
static_assert ( std :: is_trivially_move_assignable_v < length < metre >> );
static_assert ( std :: is_trivially_destructible_v < length < metre >> );
2020-09-05 21:41:02 -04:00
2020-10-06 18:17:52 +02:00
static_assert ( std :: is_nothrow_default_constructible_v < length < metre >> );
static_assert ( std :: is_nothrow_copy_constructible_v < length < metre >> );
static_assert ( std :: is_nothrow_move_constructible_v < length < metre >> );
static_assert ( std :: is_nothrow_copy_assignable_v < length < metre >> );
static_assert ( std :: is_nothrow_move_assignable_v < length < metre >> );
static_assert ( std :: is_nothrow_destructible_v < length < metre >> );
static_assert ( std :: is_trivially_copyable_v < length < metre >> );
static_assert ( std :: is_standard_layout_v < length < metre >> );
static_assert ( std :: default_initializable < length < metre >> );
static_assert ( std :: move_constructible < length < metre >> );
static_assert ( std :: copy_constructible < length < metre >> );
static_assert ( std :: equality_comparable < length < metre >> );
static_assert ( std :: totally_ordered < length < metre >> );
static_assert ( std :: regular < length < metre >> );
static_assert ( std :: three_way_comparable < length < metre >> );
//////////////////
2019-12-04 17:46:19 +01:00
// member types
2020-10-06 18:17:52 +02:00
//////////////////
2018-09-28 07:47:37 -07:00
2020-10-06 18:17:52 +02:00
static_assert ( is_same_v < length < metre , int >:: dimension , dim_length > );
static_assert ( is_same_v < fps :: length < fps :: mile >:: dimension , fps :: dim_length > );
2020-06-29 20:30:59 +02:00
static_assert ( is_same_v < length < metre , int >:: unit , metre > );
2020-10-06 18:17:52 +02:00
static_assert ( is_same_v < fps :: length < fps :: mile >:: unit , fps :: mile > );
static_assert ( is_same_v < length < metre , int >:: rep , int > );
static_assert ( is_same_v < fps :: length < fps :: mile >:: rep , double > );
2018-09-28 07:47:37 -07:00
2020-10-06 18:17:52 +02:00
////////////////////////////
2019-12-04 17:46:19 +01:00
// static member functions
2020-10-06 18:17:52 +02:00
////////////////////////////
2018-09-28 07:47:37 -07:00
2019-12-04 17:46:19 +01:00
static_assert ( length < metre , int >:: zero (). count () == 0 );
static_assert ( length < metre , int >:: min (). count () == std :: numeric_limits < int >:: lowest ());
static_assert ( length < metre , int >:: max (). count () == std :: numeric_limits < int >:: max ());
static_assert ( length < metre , double >:: zero (). count () == 0.0 );
static_assert ( length < metre , double >:: min (). count () == std :: numeric_limits < double >:: lowest ());
static_assert ( length < metre , double >:: max (). count () == std :: numeric_limits < double >:: max ());
2018-09-28 07:47:37 -07:00
2020-10-06 18:17:52 +02:00
//////////////////////////////
// construction from a value
//////////////////////////////
2018-09-28 07:47:37 -07:00
2020-10-06 18:17:52 +02:00
// only explicit construction from a value
static_assert ( std :: constructible_from < length < metre > , double > );
static_assert ( ! std :: convertible_to < double , length < metre >> );
2018-09-28 07:47:37 -07:00
2020-10-06 18:17:52 +02:00
static_assert ( std :: constructible_from < length < metre > , float > );
static_assert ( ! std :: convertible_to < float , length < metre >> );
static_assert ( std :: constructible_from < length < metre , float > , double > ); // truncating implicit conversions double -> float allowed
static_assert ( ! std :: convertible_to < double , length < metre , float >> );
static_assert ( std :: constructible_from < length < metre > , int > );
static_assert ( ! std :: convertible_to < int , length < metre >> );
static_assert ( std :: constructible_from < length < metre > , short > );
static_assert ( ! std :: convertible_to < short , length < metre >> );
static_assert ( std :: constructible_from < length < metre , short > , int > ); // truncating implicit conversions int -> short allowed
static_assert ( ! std :: convertible_to < int , length < metre , short >> );
// exception, implicit construction from a value allowed for a dimensionless quantity
static_assert ( std :: constructible_from < dimensionless < one > , double > );
static_assert ( std :: convertible_to < double , dimensionless < one >> );
static_assert ( std :: constructible_from < dimensionless < one > , float > );
static_assert ( std :: convertible_to < float , dimensionless < one >> );
static_assert ( std :: constructible_from < dimensionless < one , float > , double > );
static_assert ( std :: convertible_to < double , dimensionless < one , float >> );
static_assert ( std :: constructible_from < dimensionless < one > , int > );
static_assert ( std :: convertible_to < int , dimensionless < one >> );
static_assert ( std :: constructible_from < dimensionless < one > , short > );
static_assert ( std :: convertible_to < short , dimensionless < one >> );
static_assert ( std :: constructible_from < dimensionless < one , short > , int > );
static_assert ( std :: convertible_to < int , dimensionless < one , short >> );
// but only if a dimensionless quantity has a ratio(1)
static_assert ( std :: constructible_from < dimensionless < percent > , double > );
static_assert ( ! std :: convertible_to < double , dimensionless < percent >> );
static_assert ( std :: constructible_from < dimensionless < percent > , float > );
static_assert ( ! std :: convertible_to < float , dimensionless < percent >> );
static_assert ( std :: constructible_from < dimensionless < percent , float > , double > ); // truncating implicit conversions double -> float allowed
static_assert ( ! std :: convertible_to < double , dimensionless < percent , float >> );
static_assert ( std :: constructible_from < dimensionless < percent > , int > );
static_assert ( ! std :: convertible_to < int , dimensionless < percent >> );
static_assert ( std :: constructible_from < dimensionless < percent > , short > );
static_assert ( ! std :: convertible_to < short , dimensionless < percent >> );
static_assert ( std :: constructible_from < dimensionless < percent , short > , int > ); // truncating implicit conversions int -> short allowed
static_assert ( ! std :: convertible_to < int , dimensionless < percent , short >> );
// floating-point to integral truncating conversion not allowed
static_assert ( ! std :: constructible_from < length < metre , int > , double > );
static_assert ( ! std :: convertible_to < double , length < metre , int >> );
static_assert ( ! std :: constructible_from < dimensionless < one , int > , double > );
static_assert ( ! std :: convertible_to < double , dimensionless < one , int >> );
static_assert ( length < metre , int > (). count () == 0 ); // value initialization
static_assert ( length < metre , int > ( 1 ). count () == 1 );
static_assert ( length < metre , double > ( 1.0 ). count () == 1.0 );
static_assert ( length < metre , double > ( 1 ). count () == 1.0 );
static_assert ( length < metre , double > ( 3.14 ). count () == 3.14 );
///////////////////////////////////////
// construction from another quantity
///////////////////////////////////////
// conversion only between equivalent dimensions
static_assert ( std :: constructible_from < length < metre > , length < metre >> );
static_assert ( std :: convertible_to < length < metre > , length < metre >> );
static_assert ( std :: constructible_from < length < centimetre > , cgs :: length < cgs :: centimetre >> );
static_assert ( std :: convertible_to < cgs :: length < cgs :: centimetre > , length < centimetre >> );
static_assert ( std :: constructible_from < fps :: length < fps :: foot > , cgs :: length < cgs :: centimetre >> );
static_assert ( std :: convertible_to < cgs :: length < cgs :: centimetre > , fps :: length < fps :: foot >> );
// conversion between different dimensions not allowed
static_assert ( ! std :: constructible_from < length < metre > , physical :: si :: time < second >> );
static_assert ( ! std :: convertible_to < physical :: si :: time < second > , length < metre >> );
static_assert ( ! std :: constructible_from < length < metre > , speed < metre_per_second >> );
static_assert ( ! std :: convertible_to < speed < metre_per_second > , length < metre >> );
// implicit conversion from another quantity only if non-truncating
static_assert ( std :: constructible_from < length < metre > , length < metre , int >> ); // int -> double OK
static_assert ( std :: convertible_to < length < metre , int > , length < metre >> ); // int -> double OK
static_assert ( ! std :: constructible_from < length < metre , int > , length < metre >> ); // truncating double -> int not allowed
static_assert ( ! std :: convertible_to < length < metre > , length < metre , int >> ); // truncating double -> int not allowed
static_assert ( std :: constructible_from < length < metre , int > , length < kilometre , int >> ); // kilometre<int> -> metre<int> OK
static_assert ( std :: convertible_to < length < kilometre , int > , length < metre , int >> ); // kilometre<int> -> metre<int> OK
static_assert ( ! std :: constructible_from < length < kilometre , int > , length < metre , int >> ); // truncating metre<int> -> kilometre<int> not allowed
static_assert ( ! std :: convertible_to < length < metre , int > , length < kilometre , int >> ); // truncating metre<int> -> kilometre<int> not allowed
// converting to double always OK
static_assert ( std :: constructible_from < length < metre > , length < kilometre , int >> );
static_assert ( std :: convertible_to < length < kilometre , int > , length < metre >> );
static_assert ( std :: constructible_from < length < kilometre > , length < metre , int >> );
static_assert ( std :: convertible_to < length < metre , int > , length < kilometre >> );
static_assert ( length < metre , int > ( 123 _q_m ). count () == 123 );
static_assert ( length < kilometre , int > ( 2 _q_km ). count () == 2 );
static_assert ( length < metre , int > ( 2 _q_km ). count () == 2000 );
static_assert ( length < kilometre > ( 1500 _q_m ). count () == 1.5 );
/////////
// CTAD
/////////
static_assert ( std :: is_same_v < decltype ( quantity { length < metre , int > ( 123 )}), length < metre , int >> );
static_assert ( std :: is_same_v < decltype ( quantity { speed < metre_per_second > ( 123 )}), speed < metre_per_second >> );
// static_assert(std::is_same_v<decltype(length{length<metre, int>(123)}), length<metre, int>>); // TODO gcc ICE
static_assert ( std :: is_same_v < decltype ( quantity { 123 _q_m }), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( quantity { 1 }), dimensionless < one , int >> );
static_assert ( std :: is_same_v < decltype ( quantity { 1.23 }), dimensionless < one , double >> );
////////////////////////
// assignment operator
////////////////////////
static_assert ([]() { length < metre , int > l1 ( 1 ), l2 ( 2 ); return l2 = l1 ; }(). count () == 1 );
static_assert ([]() { length < metre , int > l1 ( 1 ), l2 ( 2 ); return l2 = std :: move ( l1 ); }(). count () == 1 );
////////////////////
// unary operators
////////////////////
static_assert (( + 123 _q_m ). count () == 123 );
static_assert (( - 123 _q_m ). count () == - 123 );
static_assert (( + ( - 123 _q_m )). count () == - 123 );
static_assert (( - ( - 123 _q_m )). count () == 123 );
static_assert ([]( auto v ) { auto vv = v ++ ; return std :: pair ( v , vv ); }( 123 _q_m ) == std :: pair ( 124 _q_m , 123 _q_m ));
static_assert ([]( auto v ) { auto vv = ++ v ; return std :: pair ( v , vv ); }( 123 _q_m ) == std :: pair ( 124 _q_m , 124 _q_m ));
static_assert ([]( auto v ) { auto vv = v -- ; return std :: pair ( v , vv ); }( 123 _q_m ) == std :: pair ( 122 _q_m , 123 _q_m ));
static_assert ([]( auto v ) { auto vv = -- v ; return std :: pair ( v , vv ); }( 123 _q_m ) == std :: pair ( 122 _q_m , 122 _q_m ));
////////////////////////
2019-12-04 17:46:19 +01:00
// compound assignment
2020-10-06 18:17:52 +02:00
////////////////////////
2018-09-28 07:47:37 -07:00
2020-10-06 18:17:52 +02:00
// same type
2020-09-09 19:20:35 +02:00
static_assert (( 1 _q_m += 1 _q_m ). count () == 2 );
static_assert (( 2 _q_m -= 1 _q_m ). count () == 1 );
static_assert (( 1 _q_m *= 2 ). count () == 2 );
static_assert (( 2 _q_m /= 2 ). count () == 1 );
static_assert (( 7 _q_m %= 2 ). count () == 1 );
static_assert (( 7 _q_m %= 2 _q_m ). count () == 1 );
2018-09-28 07:47:37 -07:00
2020-10-06 18:17:52 +02:00
// different types
2020-09-09 19:20:35 +02:00
static_assert (( 2.5 _q_m += 3 _q_m ). count () == 5.5 );
2020-10-06 18:17:52 +02:00
static_assert (( 123 _q_m += 1 _q_km ). count () == 1123 );
static_assert (( 5.5 _q_m -= 3 _q_m ). count () == 2.5 );
static_assert (( 1123 _q_m -= 1 _q_km ). count () == 123 );
2020-09-09 19:20:35 +02:00
static_assert (( 2.5 _q_m *= 3 ). count () == 7.5 );
2020-10-06 18:17:52 +02:00
static_assert (( 7.5 _q_m /= 3 ). count () == 2.5 );
static_assert (( 3500 _q_m %= 1 _q_km ). count () == 500 );
2020-08-16 13:29:40 +02:00
2020-09-05 21:41:02 -04:00
template < typename Metre >
2020-10-06 18:17:52 +02:00
concept invalid_compound_assignments = requires () {
// truncating not allowed
requires ! requires ( length < Metre , int > l ) { l += 2.5 _q_m ; };
requires ! requires ( length < Metre , int > l ) { l -= 2.5 _q_m ; };
requires ! requires ( length < kilometre , int > l ) { l += length < Metre , int > ( 2 ); };
requires ! requires ( length < kilometre , int > l ) { l -= length < Metre , int > ( 2 ); };
requires ! requires ( length < kilometre , int > l ) { l %= length < Metre , int > ( 2 ); };
// only quantities can be added or subtracted
requires ! requires ( length < Metre , int > l ) { l += 2 ; };
requires ! requires ( length < Metre , int > l ) { l -= 2 ; };
// compound multiply/divide by another quantity not allowed
requires ! requires ( length < Metre , int > l ) { l *= 2 _q_m ; };
requires ! requires ( length < Metre , int > l ) { l /= 2 _q_m ; };
// modulo operations on a floating point representation not allowed
2020-09-23 16:38:40 +02:00
requires ! requires ( length < Metre , double > l ) { l %= 2. ; };
requires ! requires ( length < Metre , double > l ) { l %= 2 ; };
requires ! requires ( length < Metre , double > l ) { l %= 2. _q_m ; };
requires ! requires ( length < Metre , double > l ) { l %= 2 _q_m ; };
requires ! requires ( length < Metre , int > l ) { l %= 2. _q_m ; };
2020-09-05 21:41:02 -04:00
};
static_assert ( invalid_compound_assignments < metre > );
2018-09-28 07:47:37 -07:00
2020-10-06 18:17:52 +02:00
////////////////////
// binary operators
////////////////////
2018-09-28 07:47:37 -07:00
2020-10-06 18:17:52 +02:00
template < typename Metre >
concept invalid_binary_operations = requires {
// no crossdimensional addition and subtraction
requires ! requires { 1 _q_s + length < Metre , int > ( 1 ); };
requires ! requires { 1 _q_s - length < Metre , int > ( 1 ); };
// no floating-point modulo
requires ! requires ( length < Metre , double > a ) { a % 2 _q_m ; };
requires ! requires ( length < Metre , double > a ) { 2 _q_m % a ; };
requires ! requires ( length < Metre , double > a ) { a % 2 ; };
requires ! requires ( length < Metre , double > a , length < Metre , double > b ) { a % b ; };
requires ! requires ( length < Metre , double > a , length < Metre , int > b ) { a % b ; };
requires ! requires ( length < Metre , double > a , length < Metre , int > b ) { b % a ; };
};
static_assert ( invalid_binary_operations < metre > );
// same representation type
static_assert ( std :: is_same_v < decltype ( 1 _q_m + 1 _q_m ), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m - 1 _q_m ), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m * 1 ), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m * quantity { 1 }), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1 * 1 _q_m ), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( quantity { 1 } * 1 _q_m ), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m / 1 ), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m / quantity { 1 }), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m % 1 ), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m % quantity { 1 }), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m % 1 _q_m ), length < metre , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_m * dimensionless < percent , std :: int64_t > ( 1 )), length < centimetre , std :: int64_t >> );
static_assert ( compare < decltype ( dimensionless < percent , std :: int64_t > ( 1 ) * 1 _q_m ), length < centimetre , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_m / dimensionless < percent , std :: int64_t > ( 1 )), length < hectometre , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_m % dimensionless < percent , std :: int64_t > ( 1 )), length < centimetre , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_m * 1 _q_m ), area < square_metre , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_m / 1 _q_m ), dimensionless < one , std :: int64_t >> );
static_assert ( compare < decltype ( 1 / 1 _q_s ), frequency < hertz , std :: int64_t >> );
static_assert ( compare < decltype ( quantity { 1 } / 1 _q_s ), frequency < hertz , std :: int64_t >> );
static_assert ( compare < decltype ( dimensionless < percent , std :: int64_t > ( 1 ) / 1 _q_s ), frequency < scaled_unit < ratio ( 1 , 100 ), hertz > , std :: int64_t >> );
// different representation types
static_assert ( std :: is_same_v < decltype ( 1 _q_m + 1. _q_m ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m - 1. _q_m ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m * 1. L ), length < metre , long double >> ); // TODO should we address fundamental types implicit truncating conversions with concepts?
static_assert ( std :: is_same_v < decltype ( 1 * 1. _q_m ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m * quantity { 1. L }), length < metre , long double >> ); // TODO should we address fundamental types implicit truncating conversions with concepts?
static_assert ( std :: is_same_v < decltype ( quantity { 1 } * 1. _q_m ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m / 1. L ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m / quantity { 1. L }), length < metre , long double >> );
static_assert ( compare < decltype ( 1 _q_m * dimensionless < percent , long double > ( 1 )), length < centimetre , long double >> );
static_assert ( compare < decltype ( dimensionless < percent , std :: int64_t > ( 1 ) * 1. _q_m ), length < centimetre , long double >> );
static_assert ( compare < decltype ( 1 _q_m * 1. _q_m ), area < square_metre , long double >> );
static_assert ( compare < decltype ( 1 _q_m / dimensionless < percent , long double > ( 1 )), length < hectometre , long double >> );
static_assert ( compare < decltype ( 1 _q_m / 1. _q_m ), dimensionless < one , long double >> );
static_assert ( compare < decltype ( 1 / 1. _q_s ), frequency < hertz , long double >> );
static_assert ( compare < decltype ( quantity { 1 } / 1. _q_s ), frequency < hertz , long double >> );
static_assert ( compare < decltype ( dimensionless < percent , std :: int64_t > ( 1 ) / 1. _q_s ), frequency < scaled_unit < ratio ( 1 , 100 ), hertz > , long double >> );
static_assert ( compare < decltype ( 1 _q_m % short ( 1 )), length < metre , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_m % quantity { short ( 1 )}), length < metre , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_m % dimensionless < percent , short > ( 1 )), length < centimetre , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_m % length < metre , short > ( 1 )), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1. _q_m + 1 _q_m ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1. _q_m - 1 _q_m ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1. _q_m * 1 ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1. L * 1 _q_m ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1. _q_m * quantity { 1 }), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( quantity { 1. L } * 1 _q_m ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1. _q_m / 1 ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1. _q_m / quantity { 1 }), length < metre , long double >> );
static_assert ( compare < decltype ( 1. _q_m * dimensionless < percent , std :: int64_t > ( 1 )), length < centimetre , long double >> );
static_assert ( compare < decltype ( dimensionless < percent , long double > ( 1 ) * 1 _q_m ), length < centimetre , long double >> );
static_assert ( compare < decltype ( 1. _q_m / dimensionless < percent , std :: int64_t > ( 1 )), length < hectometre , long double >> );
static_assert ( compare < decltype ( 1. _q_m * 1 _q_m ), area < square_metre , long double >> );
static_assert ( compare < decltype ( 1. _q_m / 1 _q_m ), dimensionless < one , long double >> );
static_assert ( compare < decltype ( 1. L / 1 _q_s ), frequency < hertz , long double >> );
static_assert ( compare < decltype ( quantity { 1. L } / 1 _q_s ), frequency < hertz , long double >> );
static_assert ( compare < decltype ( dimensionless < percent , long double > ( 1 ) / 1 _q_s ), frequency < scaled_unit < ratio ( 1 , 100 ), hertz > , long double >> );
// different units
static_assert ( std :: is_same_v < decltype ( 1 _q_m + 1 _q_km ), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1. _q_m + 1 _q_km ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m + 1. _q_km ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1. _q_m + 1. _q_km ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_km + 1 _q_m ), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1. _q_km + 1 _q_m ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_km + 1. _q_m ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1. _q_km + 1. _q_m ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m - 1 _q_km ), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1. _q_m - 1 _q_km ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m - 1. _q_km ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1. _q_m - 1. _q_km ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_km - 1 _q_m ), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1. _q_km - 1 _q_m ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_km - 1. _q_m ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1. _q_km - 1. _q_m ), length < metre , long double >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_m % 1 _q_km ), length < metre , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_km % 1 _q_m ), length < metre , std :: int64_t >> );
// different dimensions
static_assert ( compare < decltype ( 1 _q_m_per_s * 1 _q_s ), length < metre , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_m_per_s * 1 _q_h ), length < scaled_unit < ratio ( 36 , 1 , 2 ), metre > , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_m * 1 _q_min ), quantity < unknown_dimension < exponent < dim_length , 1 > , exponent < dim_time , 1 >> , scaled_unit < ratio ( 60 ), unknown_coherent_unit > , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_s * 1 _q_Hz ), dimensionless < one , std :: int64_t >> );
static_assert ( compare < decltype ( 1 / 1 _q_min ), frequency < scaled_unit < ratio ( 1 , 60 ), hertz > , std :: int64_t >> );
static_assert ( compare < decltype ( 1 / 1 _q_Hz ), physical :: si :: time < second , std :: int64_t >> );
static_assert ( compare < decltype ( 1 / 1 _q_km ), quantity < unknown_dimension < exponent < dim_length , - 1 >> , scaled_unit < ratio ( 1 , 1 , - 3 ), unknown_coherent_unit > , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_km / 1 _q_m ), dimensionless < scaled_unit < ratio ( 1000 ), one > , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_m / 1 _q_s ), speed < metre_per_second , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_m / 1 _q_min ), speed < scaled_unit < ratio ( 1 , 60 ), metre_per_second > , std :: int64_t >> );
static_assert ( compare < decltype ( 1 _q_min / 1 _q_m ), quantity < unknown_dimension < exponent < dim_length , - 1 > , exponent < dim_time , 1 >> , scaled_unit < ratio ( 60 ), unknown_coherent_unit > , std :: int64_t >> );
static_assert (( 1 _q_m + 1 _q_m ). count () == 2 );
2020-09-09 19:20:35 +02:00
static_assert (( 1 _q_m + 1 _q_km ). count () == 1001 );
2020-10-06 18:17:52 +02:00
static_assert (( 1 _q_km + 1 _q_m ). count () == 1001 );
static_assert (( 2 _q_m - 1 _q_m ). count () == 1 );
2020-09-09 19:20:35 +02:00
static_assert (( 1 _q_km - 1 _q_m ). count () == 999 );
static_assert (( 2 _q_m * 2 ). count () == 4 );
2020-10-06 18:17:52 +02:00
static_assert (( 2 _q_m * quantity { 2 }). count () == 4 );
static_assert (( 2 _q_m * dimensionless < percent , int > ( 2 )). count () == 4 );
2020-09-09 19:20:35 +02:00
static_assert (( 3 * 3 _q_m ). count () == 9 );
2020-10-06 18:17:52 +02:00
static_assert (( quantity { 3 } * 3 _q_m ). count () == 9 );
static_assert (( dimensionless < percent , int > ( 3 ) * 3 _q_m ). count () == 9 );
2020-09-09 19:20:35 +02:00
static_assert (( 4 _q_m / 2 ). count () == 2 );
2020-10-06 18:17:52 +02:00
static_assert (( 4 _q_m / quantity { 2 }). count () == 2 );
static_assert (( 4 _q_m / dimensionless < percent , int > ( 2 )). count () == 2 );
2020-09-09 19:20:35 +02:00
static_assert (( 4 _q_km / 2 _q_m ). count () == 2 );
static_assert (( 4000 _q_m / 2 _q_m ). count () == 2000 );
2020-10-06 18:17:52 +02:00
static_assert (( 1.5 _q_m + 1 _q_m ). count () == 2.5 );
static_assert (( 1.5 _q_m + 1 _q_km ). count () == 1001.5 );
static_assert (( 1.5 _q_km + 1 _q_m ). count () == 1501 );
static_assert (( 2.5 _q_m - 1 _q_m ). count () == 1.5 );
static_assert (( 1.5 _q_km - 1 _q_m ). count () == 1499 );
static_assert (( 2.5 _q_m * 2 ). count () == 5 );
static_assert (( 2.5 _q_m * quantity { 2 }). count () == 5 );
static_assert (( 2.5 _q_m * dimensionless < percent , int > ( 2 )). count () == 5 );
static_assert (( 2.5 L * 2 _q_m ). count () == 5 );
static_assert (( quantity { 2.5 L } * 2 _q_m ). count () == 5 );
static_assert (( dimensionless < percent , long double > ( 2.5 L ) * 2 _q_m ). count () == 5 );
static_assert (( 5. _q_m / 2 ). count () == 2.5 );
static_assert (( 5. _q_m / quantity { 2 }). count () == 2.5 );
static_assert (( 5. _q_m / dimensionless < percent , int > ( 2 )). count () == 2.5 );
static_assert (( 5. _q_km / 2 _q_m ). count () == 2.5 );
static_assert (( 5000. _q_m / 2 _q_m ). count () == 2500 );
static_assert (( 1 _q_m + 1.5 _q_m ). count () == 2.5 );
static_assert (( 1 _q_m + 1.5 _q_km ). count () == 1501 );
static_assert (( 1 _q_km + 1.5 _q_m ). count () == 1001.5 );
static_assert (( 2 _q_m - 1.5 _q_m ). count () == 0.5 );
static_assert (( 1 _q_km - 1.5 _q_m ). count () == 998.5 );
static_assert (( 2 _q_m * 2.5 L ). count () == 5 );
static_assert (( 2 _q_m * quantity { 2.5 L }). count () == 5 );
static_assert (( 2 _q_m * dimensionless < percent , long double > ( 2.5 L )). count () == 5 );
static_assert (( 2 * 2.5 _q_m ). count () == 5 );
static_assert (( quantity { 2 } * 2.5 _q_m ). count () == 5 );
static_assert (( dimensionless < percent , int > ( 2 ) * 2.5 _q_m ). count () == 5 );
static_assert (( 5 _q_m / 2.5 L ). count () == 2 );
static_assert (( 5 _q_m / quantity { 2.5 L }). count () == 2 );
static_assert (( 5 _q_m / dimensionless < percent , long double > ( 2.5 L )). count () == 2 );
static_assert (( 5 _q_km / 2.5 _q_m ). count () == 2 );
static_assert (( 5000 _q_m / 2.5 _q_m ). count () == 2000 );
2020-09-09 19:20:35 +02:00
static_assert (( 7 _q_m % 2 ). count () == 1 );
2020-10-06 18:17:52 +02:00
static_assert (( 7 _q_m % quantity { 2 }). count () == 1 );
static_assert (( 7 _q_m % dimensionless < percent , int > ( 2 )). count () == 1 );
2020-09-09 19:20:35 +02:00
static_assert (( 7 _q_m % 2 _q_m ). count () == 1 );
static_assert (( 7 _q_km % 2000 _q_m ). count () == 1000 );
2018-09-28 07:47:37 -07:00
2020-09-09 19:20:35 +02:00
static_assert (( 10 _q_km2 * 10 _q_km2 ) / 50 _q_km2 == 2 _q_km2 );
2019-12-12 15:39:04 +01:00
2020-10-06 18:17:52 +02:00
static_assert (( 10 _q_km / 5 _q_m ). count () == 2 );
static_assert ( dimensionless < one > ( 10 _q_km / 5 _q_m ). count () == 2000 );
2020-09-08 11:02:16 +02:00
2020-09-13 18:45:46 +02:00
#if UNITS_DOWNCAST_MODE == 0
2020-10-06 18:17:52 +02:00
static_assert ( quantity_cast < dim_one , one > ( 10 _q_km / 5 _q_m ). count () == 2000 );
2020-09-10 11:33:58 +02:00
#else
2020-10-06 18:17:52 +02:00
static_assert ( quantity_cast < one > ( 10 _q_km / 5 _q_m ). count () == 2000 );
2020-09-10 11:33:58 +02:00
#endif
2020-09-08 11:02:16 +02:00
2020-10-06 18:17:52 +02:00
static_assert (( 10 _q_s * 2 _q_kHz ). count () == 20 );
2020-09-08 11:02:16 +02:00
2018-09-28 07:47:37 -07:00
2020-10-06 18:17:52 +02:00
// dimensionless
2018-09-28 07:47:37 -07:00
2020-10-06 18:17:52 +02:00
static_assert ( quantity { 1 } + quantity { 1 } == 2 );
static_assert ( 1 + quantity { 1 } == 2 );
static_assert ( quantity { 1 } + 1 == 2 );
static_assert ( quantity { 2 } - quantity { 1 } == 1 );
static_assert ( 2 - quantity { 1 } == 1 );
static_assert ( quantity { 2 } - 1 == 1 );
static_assert ( quantity { 2 } * quantity { 2 } == 4 );
static_assert ( 2 * quantity { 2 } == 4 );
static_assert ( quantity { 2 } * 2 == 4 );
static_assert ( quantity { 4 } / quantity { 2 } == 2 );
static_assert ( 4 / quantity { 2 } == 2 );
static_assert ( quantity { 4 } / 2 == 2 );
static_assert ( quantity { 4 } % quantity { 2 } == 0 );
static_assert ( 4 % quantity { 2 } == 0 );
static_assert ( quantity { 4 } % 2 == 0 );
2018-09-28 07:47:37 -07:00
2018-08-22 12:11:19 +02:00
2020-10-06 18:17:52 +02:00
///////////////////////
// equality operators
///////////////////////
2020-05-08 21:18:16 +02:00
2020-10-06 18:17:52 +02:00
template < typename Metre >
concept no_crossdimensional_equality = requires {
requires ! requires { 1 _q_s == length < Metre , int > ( 1 ); };
requires ! requires { 1 _q_s != length < Metre , int > ( 1 ); };
};
static_assert ( no_crossdimensional_equality < metre > );
2020-05-08 21:18:16 +02:00
2020-10-06 18:17:52 +02:00
// same type
static_assert ( length < metre , int > ( 123 ) == length < metre , int > ( 123 ));
static_assert ( length < metre , int > ( 321 ) != length < metre , int > ( 123 ));
static_assert ( ! ( length < metre , int > ( 123 ) == length < metre , int > ( 321 )));
static_assert ( ! ( length < metre , int > ( 123 ) != length < metre , int > ( 123 )));
2018-08-22 12:11:19 +02:00
2020-10-06 18:17:52 +02:00
// different types
static_assert ( length < metre , double > ( 123 ) == length < metre , int > ( 123 ));
static_assert ( length < metre , double > ( 321 ) != length < metre , int > ( 123 ));
static_assert ( ! ( length < metre , double > ( 123 ) == length < metre , int > ( 321 )));
static_assert ( ! ( length < metre , double > ( 123 ) != length < metre , int > ( 123 )));
2018-08-22 12:11:19 +02:00
2020-10-06 18:17:52 +02:00
static_assert ( length < kilometre , int > ( 123 ) == length < metre , int > ( 123000 ));
static_assert ( length < kilometre , int > ( 321 ) != length < metre , int > ( 123000 ));
static_assert ( ! ( length < kilometre , int > ( 123 ) == length < metre , int > ( 321000 )));
static_assert ( ! ( length < kilometre , int > ( 123 ) != length < metre , int > ( 123000 )));
2018-08-22 12:11:19 +02:00
2020-10-06 18:17:52 +02:00
// dimensionless
2018-08-22 12:11:19 +02:00
2020-10-06 18:17:52 +02:00
static_assert ( quantity { 123 } == 123 );
static_assert ( quantity { 321 } != 123 );
static_assert ( 123 == quantity { 123 });
static_assert ( 123 != quantity { 321 });
2020-05-28 20:19:05 +02:00
2020-10-06 18:17:52 +02:00
///////////////////////
// ordering operators
///////////////////////
template < typename Metre >
concept no_crossdimensional_ordering = requires {
requires ! requires { 1 _q_s < length < Metre , int > ( 1 ); };
requires ! requires { 1 _q_s > length < Metre , int > ( 1 ); };
requires ! requires { 1 _q_s <= length < Metre , int > ( 1 ); };
requires ! requires { 1 _q_s >= length < Metre , int > ( 1 ); };
};
static_assert ( no_crossdimensional_ordering < metre > );
// same type
static_assert ( length < metre , int > ( 123 ) < length < metre , int > ( 321 ));
static_assert ( length < metre , int > ( 123 ) <= length < metre , int > ( 123 ));
static_assert ( length < metre , int > ( 123 ) <= length < metre , int > ( 321 ));
static_assert ( length < metre , int > ( 321 ) > length < metre , int > ( 123 ));
static_assert ( length < metre , int > ( 123 ) >= length < metre , int > ( 123 ));
static_assert ( length < metre , int > ( 321 ) >= length < metre , int > ( 123 ));
static_assert ( ! ( length < metre , int > ( 321 ) < length < metre , int > ( 123 )));
static_assert ( ! ( length < metre , int > ( 123 ) < length < metre , int > ( 123 )));
static_assert ( ! ( length < metre , int > ( 321 ) <= length < metre , int > ( 123 )));
static_assert ( ! ( length < metre , int > ( 123 ) > length < metre , int > ( 321 )));
static_assert ( ! ( length < metre , int > ( 123 ) > length < metre , int > ( 123 )));
static_assert ( ! ( length < metre , int > ( 123 ) >= length < metre , int > ( 321 )));
// different types
static_assert ( length < metre , double > ( 123 ) < length < metre , int > ( 321 ));
static_assert ( length < metre , double > ( 123 ) <= length < metre , int > ( 123 ));
static_assert ( length < metre , double > ( 123 ) <= length < metre , int > ( 321 ));
static_assert ( length < metre , double > ( 321 ) > length < metre , int > ( 123 ));
static_assert ( length < metre , double > ( 123 ) >= length < metre , int > ( 123 ));
static_assert ( length < metre , double > ( 321 ) >= length < metre , int > ( 123 ));
static_assert ( ! ( length < metre , double > ( 321 ) < length < metre , int > ( 123 )));
static_assert ( ! ( length < metre , double > ( 123 ) < length < metre , int > ( 123 )));
static_assert ( ! ( length < metre , double > ( 321 ) <= length < metre , int > ( 123 )));
static_assert ( ! ( length < metre , double > ( 123 ) > length < metre , int > ( 321 )));
static_assert ( ! ( length < metre , double > ( 123 ) > length < metre , int > ( 123 )));
static_assert ( ! ( length < metre , double > ( 123 ) >= length < metre , int > ( 321 )));
static_assert ( length < kilometre , int > ( 123 ) < length < metre , int > ( 321000 ));
static_assert ( length < kilometre , int > ( 123 ) <= length < metre , int > ( 123000 ));
static_assert ( length < kilometre , int > ( 123 ) <= length < metre , int > ( 321000 ));
static_assert ( length < kilometre , int > ( 321 ) > length < metre , int > ( 123000 ));
static_assert ( length < kilometre , int > ( 123 ) >= length < metre , int > ( 123000 ));
static_assert ( length < kilometre , int > ( 321 ) >= length < metre , int > ( 123000 ));
static_assert ( ! ( length < kilometre , int > ( 321 ) < length < metre , int > ( 123000 )));
static_assert ( ! ( length < kilometre , int > ( 123 ) < length < metre , int > ( 123000 )));
static_assert ( ! ( length < kilometre , int > ( 321 ) <= length < metre , int > ( 123000 )));
static_assert ( ! ( length < kilometre , int > ( 123 ) > length < metre , int > ( 321000 )));
static_assert ( ! ( length < kilometre , int > ( 123 ) > length < metre , int > ( 123000 )));
static_assert ( ! ( length < kilometre , int > ( 123 ) >= length < metre , int > ( 321000 )));
// dimensionless
static_assert ( quantity { 123 } < 321 );
static_assert ( quantity { 123 } <= 123 );
static_assert ( quantity { 123 } <= 321 );
static_assert ( quantity { 321 } > 123 );
static_assert ( quantity { 123 } >= 123 );
static_assert ( quantity { 321 } >= 123 );
static_assert ( 123 < quantity { 321 });
static_assert ( 123 <= quantity { 123 });
static_assert ( 123 <= quantity { 321 });
static_assert ( 321 > quantity { 123 });
static_assert ( 123 >= quantity { 123 });
static_assert ( 321 >= quantity { 123 });
//////////////////
// dimensionless
//////////////////
2020-09-09 11:22:58 +02:00
static_assert ( std :: equality_comparable_with < dimensionless < one > , int > );
static_assert ( std :: equality_comparable_with < dimensionless < one > , double > );
static_assert ( std :: equality_comparable_with < dimensionless < one , int > , int > );
static_assert ( ! std :: equality_comparable_with < dimensionless < one , int > , double > );
2020-05-28 20:19:05 +02:00
2020-09-09 02:22:34 -04:00
template < typename Int >
2020-10-06 18:17:52 +02:00
concept invalid_dimensionless_operations = requires {
2020-09-23 16:38:40 +02:00
requires ! requires ( dimensionless < one , Int > d ) { d + 1.23 ; };
requires ! requires ( dimensionless < one , Int > d ) { 1.23 + d ; };
2020-10-06 18:17:52 +02:00
requires ! requires ( dimensionless < percent , Int > d ) { 1 + d ; };
requires ! requires ( dimensionless < percent , Int > d ) { d + 1 ; };
2020-09-08 11:02:16 +02:00
};
2020-09-09 02:23:49 -04:00
static_assert ( invalid_dimensionless_operations < int > );
2020-09-08 11:02:16 +02:00
2020-09-10 00:35:25 +02:00
static_assert ( compare < decltype ( 10 _q_km / 5 _q_km ), quantity < dim_one , one , std :: int64_t >> );
2020-09-08 18:45:14 +02:00
2020-09-13 18:45:46 +02:00
#if UNITS_DOWNCAST_MODE == 0
2020-09-10 13:01:38 +02:00
static_assert ( quantity_cast < dim_one , percent > ( 50. _q_m / 100. _q_m ). count () == 50 );
2020-09-10 11:33:58 +02:00
#else
2020-09-09 19:20:35 +02:00
static_assert ( quantity_cast < percent > ( 50. _q_m / 100. _q_m ). count () == 50 );
2020-09-10 11:33:58 +02:00
#endif
2020-09-09 19:20:35 +02:00
static_assert ( 50. _q_m / 100. _q_m == dimensionless < percent > ( 50 ));
2020-09-08 11:02:16 +02:00
2020-09-09 11:22:58 +02:00
static_assert ( dimensionless < one > ( dimensionless < percent > ( 50 )). count () == 0.5 );
2020-09-08 11:02:16 +02:00
2020-09-23 16:34:13 +02:00
2020-10-06 18:17:52 +02:00
////////////////
// alias units
////////////////
2018-08-22 12:11:19 +02:00
2020-10-06 18:17:52 +02:00
static_assert ( compare < decltype ( 2 _q_l + 2 _q_ml ), volume < cubic_centimetre , std :: int64_t >> );
static_assert ( 2 _q_l + 2 _q_ml == 2002 _q_cm3 );
static_assert ( 2 _q_l + 2 _q_ml == 2002 _q_ml );
static_assert ( 2 _q_l + 2 _q_cm3 == 2002 _q_ml );
static_assert ( 2 _q_dm3 + 2 _q_cm3 == 2002 _q_ml );
2018-08-22 12:11:19 +02:00
2020-09-05 21:41:02 -04:00
2020-10-06 18:17:52 +02:00
//////////////////
// quantity_cast
//////////////////
2020-09-05 21:41:02 -04:00
2020-10-06 18:17:52 +02:00
static_assert ( compare < decltype ( quantity_cast < scaled_unit < ratio ( 1 ), metre >> ( 2 _q_km )) :: unit , metre > );
2018-08-22 12:11:19 +02:00
2020-10-06 18:17:52 +02:00
static_assert ( quantity_cast < length < metre , int >> ( 2 _q_km ). count () == 2000 );
static_assert ( quantity_cast < length < kilometre , int >> ( 2000 _q_m ). count () == 2 );
static_assert ( quantity_cast < length < metre , int >> ( 1.23 _q_m ). count () == 1 );
static_assert ( quantity_cast < metre > ( 2 _q_km ). count () == 2000 );
static_assert ( quantity_cast < kilometre > ( 2000 _q_m ). count () == 2 );
static_assert ( quantity_cast < int > ( 1.23 _q_m ). count () == 1 );
static_assert ( quantity_cast < dim_speed , kilometre_per_hour > ( 2000.0 _q_m / 3600.0 _q_s ). count () == 2 );
2018-08-22 12:11:19 +02:00
2020-05-08 10:50:34 +02:00
2020-10-06 18:17:52 +02:00
////////////////
2020-05-08 10:50:34 +02:00
// downcasting
2020-10-06 18:17:52 +02:00
////////////////
2020-05-08 10:50:34 +02:00
2020-09-13 18:45:46 +02:00
#if UNITS_DOWNCAST_MODE == 0
2020-05-08 10:50:34 +02:00
2020-09-10 11:33:58 +02:00
static_assert ( std :: is_same_v < decltype ( 10 _q_m / 5 _q_s ), quantity < unknown_dimension < units :: exponent < dim_length , 1 > , units :: exponent < dim_time , - 1 >> , scaled_unit < ratio ( 1 ), unknown_coherent_unit > , std :: int64_t >> );
2020-09-09 20:31:03 +02:00
static_assert ( std :: is_same_v < decltype ( 1 _q_mm + 1 _q_km ), length < scaled_unit < ratio ( 1 , 1 , - 3 ), metre > , std :: int64_t >> );
2020-05-08 10:50:34 +02:00
#else
2020-09-09 20:31:03 +02:00
static_assert ( std :: is_same_v < decltype ( 10 _q_m / 5 _q_s ), speed < metre_per_second , std :: int64_t >> );
static_assert ( std :: is_same_v < decltype ( 1 _q_mm + 1 _q_km ), length < millimetre , std :: int64_t >> );
2020-05-08 10:50:34 +02:00
#endif
2019-09-24 16:59:45 +02:00
2018-09-28 07:47:37 -07:00
} // namespace