// The MIT License (MIT) // // Copyright (c) 2018 Mateusz Pusz // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #pragma once #include #include #include #include template inline constexpr bool compare_impl = false; template inline constexpr bool compare_impl = true; template requires (UNITS_DOWNCAST_MODE == 0) inline constexpr bool compare_impl = units::equivalent; template inline constexpr bool compare = compare_impl, std::remove_cvref_t>; template constexpr bool constructible_from(Vs...) { return std::constructible_from; } template void convertible_from__(T); template concept convertible_from_ = requires(Us... us) { convertible_from__({us...}); }; template constexpr bool convertible_from(Vs...) { if constexpr (sizeof...(Us) + sizeof...(Vs) == 1) return std::is_convertible_v; else return convertible_from_; } template constexpr bool constructible_or_convertible_from(Vs...) { return constructible_from() || convertible_from(); } template constexpr bool constructible_and_convertible_from(Vs...) { return constructible_from() && convertible_from(); } template requires (constructible_from()) constexpr T construct_from(Us... us) { return T(us...); } template requires (convertible_from()) constexpr T convert_from(Us... us) { if constexpr (sizeof...(Us) == 1) return [](T t) { return t; }(us...); else return {us...}; } template requires (constructible_from() && convertible_from()) constexpr T construct_and_convert_from(Us... us) { T t{construct_from(us...)}; assert(t == convert_from(us...)); return t; } template requires (constructible_from() && !convertible_from()) constexpr T construct_from_only(Us... us) { return construct_from(us...); } #if !defined(UNITS_COMP_GCC) template typename T, typename = std::void_t<>, typename... Us> concept ctad_constructible_from_ = requires(Us... us) { T(us...); }; #else template typename T, typename = std::void_t<>, typename... Us> inline constexpr bool ctad_constructible_from_ = false; template typename T, typename... Us> inline constexpr bool ctad_constructible_from_, Us...> = true; #endif template typename T, typename... Us, typename... Vs> constexpr bool ctad_constructible_from(Vs...) { return ctad_constructible_from_; } #if UNITS_DOWNCAST_MODE constexpr auto same = [](T l, T r) { return l == r; }; #else constexpr auto same = [](T l, U r) requires requires { l == r; } // requires std::equality_comparable_with // TODO: Fix #205 { return l == r; }; #endif template requires requires { F(); } inline constexpr bool require_constant_invocation = requires { new int[1][(F(), 1)]; };