// The MIT License (MIT) // // Copyright (c) 2018 Mateusz Pusz // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #pragma once #include "bits/tools.h" #include "bits/type_list.h" namespace units { // dim_id template using dim_id = std::integral_constant; // dim_id_less template struct dim_id_less : std::bool_constant { }; // exp template // todo: to be replaced with fixed_string when supported by the compilers // template struct exp { using dimension = BaseDimension; static constexpr int value = Value; }; // is_exp namespace detail { template inline constexpr bool is_exp = false; template inline constexpr bool is_exp> = true; } // namespace detail template concept bool Exponent = detail::is_exp; // exp_dim_id_less template struct exp_dim_id_less : dim_id_less { }; // exp_dim_id_less template struct exp_greater_equal : std::bool_constant<(E1::value >= E2::value)> { }; // exp_invert template struct exp_invert; template struct exp_invert> { using type = exp; }; template using exp_invert_t = typename exp_invert::type; // dimension template struct dimension : upcast_base> {}; // is_dimension namespace detail { template inline constexpr bool is_dimension = false; template inline constexpr bool is_dimension> = true; } // namespace detail template concept bool Dimension = std::is_empty_v && detail::is_dimension>; // dim_invert template struct dim_invert; template struct dim_invert> : std::type_identity...>>> {}; template using dim_invert_t = typename dim_invert::type; // make_dimension namespace detail { template struct dim_consolidate; template using dim_consolidate_t = typename dim_consolidate::type; template<> struct dim_consolidate> { using type = dimension<>; }; template struct dim_consolidate> { using type = dimension; }; template struct dim_consolidate> { using rest = dim_consolidate_t>; using type = std::conditional_t>, dimension, mp::type_list_push_front_t>; }; template struct dim_consolidate, exp, ERest...>> { using type = std::conditional_t>, dim_consolidate_t, ERest...>>>; }; } // namespace detail template struct make_dimension { using type = mp::type_list_sort_t, exp_dim_id_less>>, exp_greater_equal>; }; template using make_dimension_t = typename make_dimension::type; template struct merge_dimension { using type = mp::type_list_sort_t>, exp_greater_equal>; }; template using merge_dimension_t = typename merge_dimension::type; // dimension_multiply template struct dimension_multiply; template struct dimension_multiply, dimension> : std::type_identity, dimension>>> {}; template using dimension_multiply_t = typename dimension_multiply::type; // dimension_divide template struct dimension_divide; template struct dimension_divide, dimension> : dimension_multiply, dimension...>> { }; template using dimension_divide_t = typename dimension_divide::type; } // namespace units