diff --git a/cmake/common b/cmake/common index eb5fbd40..ba5b1163 160000 --- a/cmake/common +++ b/cmake/common @@ -1 +1 @@ -Subproject commit eb5fbd40d1cb765c5a8bf50866db86082c72ef73 +Subproject commit ba5b1163c1d364c4498219a16da0ccf1557e421d diff --git a/conanfile.py b/conanfile.py index d5672cd9..40d7bbe5 100644 --- a/conanfile.py +++ b/conanfile.py @@ -72,17 +72,19 @@ class UnitsConan(ConanFile): return cmake def configure(self): - if self.settings.compiler != "gcc": # and self.settings.compiler != "clang": - raise ConanInvalidConfiguration("Library works only with gcc") # and clang") + if self.settings.compiler != "gcc" and self.settings.compiler != "Visual Studio": # and self.settings.compiler != "clang": + raise ConanInvalidConfiguration("Library works only with gcc and Visual Studio so far") # and clang") if self.settings.compiler == "gcc" and Version(self.settings.compiler.version) < "9": raise ConanInvalidConfiguration("Library requires at least g++-9") + if self.settings.compiler == "Visual Studio" and Version(self.settings.compiler.version) < "16": + raise ConanInvalidConfiguration("Library requires at least Visual Studio 2019") if self.settings.compiler == "clang" and Version(self.settings.compiler.version) < "11": raise ConanInvalidConfiguration("Library requires at least clang++-11") - if self.settings.compiler.cppstd not in ["20", "gnu20"]: - raise ConanInvalidConfiguration("Library requires at least C++20 support") + tools.check_min_cppstd(self, "20") def requirements(self): - if self.settings.compiler == "clang" or Version(self.settings.compiler.version) < "10": + if ((self.settings.compiler == "gcc" and Version(self.settings.compiler.version) < "10") or + self.settings.compiler == "clang"): self.requires("range-v3/0.11.0") def build_requirements(self): diff --git a/docs/use_cases/custom_representation_types.rst b/docs/use_cases/custom_representation_types.rst index 60d66095..f7ba006c 100644 --- a/docs/use_cases/custom_representation_types.rst +++ b/docs/use_cases/custom_representation_types.rst @@ -122,7 +122,7 @@ With C++20 it is really easy to do:: class my_rep { public: - [[nodiscard]] friend constexpr auto operator<=>(my_rep lhs, my_rep rhs) = default; + [[nodiscard]] constexpr auto operator<=>(my_rep other) const = default; // ... }; diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index a563a003..8a6fc23b 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -25,7 +25,6 @@ function(add_example target) target_link_libraries(${target} PRIVATE mp::units) endfunction() -add_example(avg_speed) add_example(box_example) add_example(capacitor_time_curve) add_example(clcpp_response) @@ -33,7 +32,6 @@ add_example(conversion_factor) add_example(experimental_angle) add_example(foot_pound_second) add_example(glide_computer) -add_example(hello_units) add_example(kalman_filter-alpha_beta_filter_example2) conan_check_testing(linear_algebra) @@ -44,7 +42,16 @@ target_link_libraries(linear_algebra ) add_example(measurement) -add_example(total_energy) add_example(unknown_dimension) +if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + +# TODO Those examples use Concepts terse syntax not yet supported by MSVC + +add_example(avg_speed) +add_example(hello_units) +add_example(total_energy) + add_subdirectory(alternative_namespaces) + +endif() diff --git a/example/glide_computer.cpp b/example/glide_computer.cpp index 9a842905..771ce780 100644 --- a/example/glide_computer.cpp +++ b/example/glide_computer.cpp @@ -28,6 +28,10 @@ #include #include +#if COMP_MSVC || COMP_GCC >= 10 +#include +#endif + // horizontal/vertical vector namespace { @@ -70,7 +74,7 @@ public: return *this; } -#if __GNUC__ >= 10 +#if COMP_MSVC || COMP_GCC >= 10 template [[nodiscard]] friend constexpr auto operator<=>(const vector& lhs, const vector& rhs) diff --git a/example/measurement.cpp b/example/measurement.cpp index 372a5e57..5691c4ef 100644 --- a/example/measurement.cpp +++ b/example/measurement.cpp @@ -24,6 +24,10 @@ #include #include +#if COMP_MSVC || COMP_GCC >= 10 +#include +#endif + namespace { // root sum of squares @@ -101,9 +105,9 @@ public: return measurement(val, val * rhs.relative_uncertainty()); } -#if __GNUC__ >= 10 +#if COMP_MSVC || COMP_GCC >= 10 - [[nodiscard]] friend constexpr auto operator<=>(const measurement& lhs, const measurement& rhs) = default; + [[nodiscard]] constexpr auto operator<=>(const measurement&) const = default; #else diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fe22dba3..915bf5b9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -70,9 +70,9 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") ) elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") target_compile_options(units - INTERFACE - -Wno-literal-suffix - -Wno-non-template-friend + INTERFACE + -Wno-literal-suffix + -Wno-non-template-friend ) if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0) @@ -85,7 +85,14 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") $,CONAN_PKG::range-v3,range-v3::range-v3> ) endif() +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + target_compile_options(units + INTERFACE + /utf-8 # Specifies both the source character set and the execution character set as UTF-8 + /wd4455 # 'operator name': literal suffix identifiers that do not start with an underscore are reserved + ) endif() + add_library(mp::units ALIAS units) # installation info diff --git a/src/include/units/bits/common_quantity.h b/src/include/units/bits/common_quantity.h index e9fc7a58..b0530395 100644 --- a/src/include/units/bits/common_quantity.h +++ b/src/include/units/bits/common_quantity.h @@ -67,7 +67,7 @@ quantity_point common_quantity_point_impl(quantity); template> requires equivalent_dim -using common_quantity = detail::common_quantity_impl::type; +using common_quantity = TYPENAME detail::common_quantity_impl::type; template requires requires { typename common_quantity; } @@ -76,7 +76,7 @@ using common_quantity_point = decltype( } // namespace units -#if COMP_GCC >= 10 +#if COMP_MSVC || COMP_GCC >= 10 namespace std { diff --git a/src/include/units/bits/dim_unpack.h b/src/include/units/bits/dim_unpack.h index cdcf9bf4..fe9c6fd4 100644 --- a/src/include/units/bits/dim_unpack.h +++ b/src/include/units/bits/dim_unpack.h @@ -48,7 +48,7 @@ struct dim_unpack, ERest...> { template struct dim_unpack, ERest...> { - using type = dim_unpack, Num, Den>, ERest...>::type; + using type = TYPENAME dim_unpack, Num, Den>, ERest...>::type; }; template diff --git a/src/include/units/bits/dimension_op.h b/src/include/units/bits/dimension_op.h index 7b8ced35..325fcef1 100644 --- a/src/include/units/bits/dimension_op.h +++ b/src/include/units/bits/dimension_op.h @@ -97,13 +97,13 @@ struct downcast_dimension_impl { template struct downcast_dimension_impl { - using type = check_unknown>::type; + using type = TYPENAME check_unknown>::type; }; } // namespace detail template -using downcast_dimension = detail::downcast_dimension_impl::type; +using downcast_dimension = TYPENAME detail::downcast_dimension_impl::type; // dim_invert namespace detail { @@ -133,7 +133,7 @@ struct dim_invert_impl : dim_invert_impl> { } // namespace detail template -using dim_invert = detail::dim_invert_impl::type; +using dim_invert = TYPENAME detail::dim_invert_impl::type; // dimension_multiply namespace detail { @@ -161,7 +161,7 @@ struct to_dimension>> { * dimension itself. */ template -using merge_dimension = to_dimension>::type>::type; +using merge_dimension = TYPENAME to_dimension>::type>::type; template struct dimension_multiply_impl; @@ -178,7 +178,7 @@ struct dimension_multiply_impl { template struct dimension_multiply_impl { - using type = dimension_multiply_impl::type; + using type = TYPENAME dimension_multiply_impl::type; }; template @@ -189,10 +189,10 @@ struct dimension_multiply_impl { } // namespace detail template -using dimension_multiply = detail::dimension_multiply_impl::type; +using dimension_multiply = TYPENAME detail::dimension_multiply_impl::type; template -using dimension_divide = detail::dimension_multiply_impl>::type; +using dimension_divide = TYPENAME detail::dimension_multiply_impl>::type; // dimension_sqrt namespace detail { @@ -212,7 +212,7 @@ struct dimension_sqrt_impl>> { template struct dimension_sqrt_impl { - using type = dimension_sqrt_impl::type; + using type = TYPENAME dimension_sqrt_impl::type; }; template @@ -223,7 +223,7 @@ struct dimension_sqrt_impl> { } // namespace detail template -using dimension_sqrt = detail::dimension_sqrt_impl::type; +using dimension_sqrt = TYPENAME detail::dimension_sqrt_impl::type; // dimension_pow namespace detail { @@ -248,7 +248,7 @@ struct dimension_pow_impl>, N> { template struct dimension_pow_impl { - using type = dimension_pow_impl, N>::type; + using type = TYPENAME dimension_pow_impl, N>::type; }; template @@ -259,6 +259,6 @@ struct dimension_pow_impl, N> { } // namespace detail template -using dimension_pow = detail::dimension_pow_impl::type; +using dimension_pow = TYPENAME detail::dimension_pow_impl::type; } // namespace units diff --git a/src/include/units/bits/external/downcasting.h b/src/include/units/bits/external/downcasting.h index 469f1556..6e269dea 100644 --- a/src/include/units/bits/external/downcasting.h +++ b/src/include/units/bits/external/downcasting.h @@ -68,6 +68,6 @@ template using downcast = decltype(detail::downcast_impl()); template -using downcast_base_t = T::downcast_base_type; +using downcast_base_t = TYPENAME T::downcast_base_type; } // namespace units diff --git a/src/include/units/bits/external/fixed_string.h b/src/include/units/bits/external/fixed_string.h index 4e531795..2f355be3 100644 --- a/src/include/units/bits/external/fixed_string.h +++ b/src/include/units/bits/external/fixed_string.h @@ -22,9 +22,15 @@ #pragma once +#include +#include #include #include +#if COMP_MSVC || COMP_GCC >= 10 +#include +#endif + namespace units { /** @@ -70,20 +76,20 @@ struct basic_fixed_string { return basic_fixed_string(txt); } -#if __GNUC__ >= 10 +#if COMP_MSVC || COMP_GCC >= 10 - template - [[nodiscard]] friend constexpr auto operator<=>(const basic_fixed_string& lhs, - const basic_fixed_string& rhs) + [[nodiscard]] constexpr bool operator==(const basic_fixed_string& other) const { - return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); + return std::ranges::equal(*this, other); } - template - [[nodiscard]] friend constexpr bool operator==(const basic_fixed_string& lhs, - const basic_fixed_string& rhs) + template + [[nodiscard]] friend constexpr bool operator==(const basic_fixed_string&, const basic_fixed_string&) { return false; } + + template + [[nodiscard]] friend constexpr auto operator<=>(const basic_fixed_string& lhs, const basic_fixed_string& rhs) { - return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); + return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } #else diff --git a/src/include/units/bits/external/hacks.h b/src/include/units/bits/external/hacks.h index 0abc58b4..9831a48f 100644 --- a/src/include/units/bits/external/hacks.h +++ b/src/include/units/bits/external/hacks.h @@ -29,9 +29,11 @@ #elif __GNUC__ #define COMP_GCC __GNUC__ #define COMP_GCC_MINOR __GNUC_MINOR__ +#elif _MSC_VER +#define COMP_MSVC _MSC_VER #endif -#if COMP_GCC >= 10 +#if COMP_MSVC || COMP_GCC >= 10 #include @@ -42,7 +44,7 @@ #endif -#if COMP_GCC >= 10 || COMP_CLANG >= 11 +#if COMP_MSVC || COMP_GCC >= 10 || COMP_CLANG >= 11 #define AUTO auto #define SAME_AS(T) std::same_as @@ -54,8 +56,19 @@ #endif +#if COMP_MSVC + +#define TYPENAME typename + +#else + +#define TYPENAME + +#endif + namespace std { +#if COMP_GCC #if COMP_GCC >= 10 template @@ -100,5 +113,6 @@ namespace std { concept regular_invocable = invocable; #endif +#endif } // namespace std diff --git a/src/include/units/bits/external/type_list.h b/src/include/units/bits/external/type_list.h index e9e67291..53d71558 100644 --- a/src/include/units/bits/external/type_list.h +++ b/src/include/units/bits/external/type_list.h @@ -24,6 +24,11 @@ #include +#ifdef _MSC_VER +#pragma warning (push) +#pragma warning (disable:4296) // warning C4296: '<': expression is always false +#endif //_MSC_VER + namespace units { namespace detail { @@ -54,7 +59,7 @@ struct type_list_push_front_impl, NewTypes...> { } // namespace detail template -using type_list_push_front = detail::type_list_push_front_impl::type; +using type_list_push_front = TYPENAME detail::type_list_push_front_impl::type; // push_back @@ -71,7 +76,7 @@ struct type_list_push_back_impl, NewTypes...> { } // namespace detail template -using type_list_push_back = detail::type_list_push_back_impl::type; +using type_list_push_back = TYPENAME detail::type_list_push_back_impl::type; // join @@ -84,13 +89,13 @@ struct type_list_join_impl { template typename List, typename... First, typename... Second, typename... Rest> struct type_list_join_impl, List, Rest...> { - using type = type_list_join_impl, Rest...>::type; + using type = TYPENAME type_list_join_impl, Rest...>::type; }; } // namespace detail template -using type_list_join = detail::type_list_join_impl::type; +using type_list_join = TYPENAME detail::type_list_join_impl::type; // split @@ -125,8 +130,8 @@ template typename List, std::size_t N, typename... Types> struct type_list_split, N> { static_assert(N <= sizeof...(Types), "Invalid index provided"); using split = detail::split_impl; - using first_list = split::first_list; - using second_list = split::second_list; + using first_list = TYPENAME split::first_list; + using second_list = TYPENAME split::second_list; }; // split_half @@ -169,7 +174,7 @@ struct type_list_merge_sorted_impl, List typename Pred> -using type_list_merge_sorted = detail::type_list_merge_sorted_impl::type; +using type_list_merge_sorted = TYPENAME detail::type_list_merge_sorted_impl::type; // sort @@ -192,14 +197,18 @@ template typename List, typename... Types, template, Pred> { using types = List; using split = type_list_split_half>; - using sorted_left = type_list_sort_impl::type; - using sorted_right = type_list_sort_impl::type; - using type = type_list_merge_sorted_impl::type; + using sorted_left = TYPENAME type_list_sort_impl::type; + using sorted_right = TYPENAME type_list_sort_impl::type; + using type = TYPENAME type_list_merge_sorted_impl::type; }; } // namespace detail template typename Pred> -using type_list_sort = detail::type_list_sort_impl::type; +using type_list_sort = TYPENAME detail::type_list_sort_impl::type; } // namespace units + +#ifdef _MSC_VER +#pragma warning (pop) +#endif //_MSC_VER diff --git a/src/include/units/bits/external/type_traits.h b/src/include/units/bits/external/type_traits.h index 4ebfb424..e3913b4b 100644 --- a/src/include/units/bits/external/type_traits.h +++ b/src/include/units/bits/external/type_traits.h @@ -22,6 +22,7 @@ #pragma once +#include #include namespace units { @@ -44,7 +45,7 @@ struct conditional_impl { } // namespace detail template -using conditional = detail::conditional_impl::template type; +using conditional = TYPENAME detail::conditional_impl::template type; // is_same template diff --git a/src/include/units/bits/ratio_maths.h b/src/include/units/bits/ratio_maths.h index 145f6746..2ef31bab 100644 --- a/src/include/units/bits/ratio_maths.h +++ b/src/include/units/bits/ratio_maths.h @@ -24,6 +24,7 @@ #include #include +#include #include #include #include diff --git a/src/include/units/bits/to_string.h b/src/include/units/bits/to_string.h index 3bd685b5..76625011 100644 --- a/src/include/units/bits/to_string.h +++ b/src/include/units/bits/to_string.h @@ -113,12 +113,12 @@ constexpr auto exp_list_with_named_units(exp_list); template constexpr auto exp_list_with_named_units(Exp) { - using dim = Exp::dimension; + using dim = TYPENAME Exp::dimension; if constexpr(dimension_unit::is_named) { return exp_list(); } else { - using recipe = dim::recipe; + using recipe = TYPENAME dim::recipe; return exp_list_with_named_units(recipe()); } } @@ -132,7 +132,7 @@ constexpr auto exp_list_with_named_units(exp_list) template constexpr auto derived_dimension_unit_text() { - using recipe = Dim::recipe; + using recipe = TYPENAME Dim::recipe; return derived_dimension_unit_text(exp_list_with_named_units(recipe())); } diff --git a/src/include/units/concepts.h b/src/include/units/concepts.h index a14d361b..1a32db76 100644 --- a/src/include/units/concepts.h +++ b/src/include/units/concepts.h @@ -174,12 +174,12 @@ struct dimension_unit_impl; template struct dimension_unit_impl { - using type = D::base_unit; + using type = TYPENAME D::base_unit; }; template struct dimension_unit_impl { - using type = D::coherent_unit; + using type = TYPENAME D::coherent_unit; }; } // namespace detail @@ -193,7 +193,7 @@ struct dimension_unit_impl { * @tparam D Dimension type to get the unit from. */ template -using dimension_unit = detail::dimension_unit_impl::type; +using dimension_unit = TYPENAME detail::dimension_unit_impl::type; /** * @brief A concept matching only units of a specified dimension. diff --git a/src/include/units/derived_dimension.h b/src/include/units/derived_dimension.h index acc0585b..e622b63f 100644 --- a/src/include/units/derived_dimension.h +++ b/src/include/units/derived_dimension.h @@ -46,7 +46,7 @@ namespace detail { * this base dimension. */ template -using make_dimension = to_derived_dimension_base::type, exp_less>>::type>::type; +using make_dimension = TYPENAME to_derived_dimension_base::type, exp_less>>::type>::type; } // namespace detail diff --git a/src/include/units/exp.h b/src/include/units/exp.h index 2b7f64f8..61cfe0d7 100644 --- a/src/include/units/exp.h +++ b/src/include/units/exp.h @@ -77,7 +77,7 @@ struct exp_multiply_impl { } // namespace detail template -using exp_multiply = detail::exp_multiply_impl::type; +using exp_multiply = TYPENAME detail::exp_multiply_impl::type; template struct exp_list {}; diff --git a/src/include/units/format.h b/src/include/units/format.h index f9ec1e23..f400de6f 100644 --- a/src/include/units/format.h +++ b/src/include/units/format.h @@ -24,9 +24,19 @@ #include #include -#include #include +#ifdef _MSC_VER +#pragma warning (push) +#pragma warning (disable:4702) // C4702: unreachable code +#endif //_MSC_VER + +#include + +#ifdef _MSC_VER +#pragma warning (pop) +#endif //_MSC_VER + // Grammar // // units-format-spec ::= [fill-and-align] [width] [units-specs] @@ -264,8 +274,12 @@ namespace units { void on_quantity_unit([[maybe_unused]] const CharT) { auto txt = unit_text(); - auto txt_c_str = unit_specs.modifier == 'A' ? txt.ascii().c_str() : txt.standard().c_str(); - format_to(out, "{}", txt_c_str); + if(unit_specs.modifier == 'A') { + format_to(out, "{}", txt.ascii().c_str()); + } + else { + format_to(out, "{}", txt.standard().c_str()); + } } }; @@ -277,7 +291,7 @@ template struct fmt::formatter, CharT> { private: using quantity = units::quantity; - using iterator = fmt::basic_format_parse_context::iterator; + using iterator = TYPENAME fmt::basic_format_parse_context::iterator; using arg_ref_type = fmt::detail::arg_ref; units::detail::global_format_specs global_specs; diff --git a/src/include/units/math.h b/src/include/units/math.h index d06965a3..4ef1f982 100644 --- a/src/include/units/math.h +++ b/src/include/units/math.h @@ -45,7 +45,7 @@ inline Quantity AUTO pow(const Q& q) noexcept { using dim = dimension_pow; using unit = downcast_unit(Q::unit::ratio)>; - using rep = Q::rep; + using rep = TYPENAME Q::rep; return quantity(static_cast(std::pow(q.count(), N))); } @@ -56,7 +56,7 @@ inline Quantity AUTO pow(const Q& q) noexcept */ template requires(N == 0) -inline Q::rep pow(const Q&) noexcept +inline TYPENAME Q::rep pow(const Q&) noexcept { return 1; } @@ -75,7 +75,7 @@ inline Quantity AUTO sqrt(const Q& q) noexcept { using dim = dimension_sqrt; using unit = downcast_unit; - using rep = Q::rep; + using rep = TYPENAME Q::rep; return quantity(static_cast(std::sqrt(q.count()))); } diff --git a/src/include/units/physical/natural/units.h b/src/include/units/physical/natural/units.h index 7d826957..3d7c71c4 100644 --- a/src/include/units/physical/natural/units.h +++ b/src/include/units/physical/natural/units.h @@ -30,8 +30,8 @@ namespace units::physical::natural { struct unitless : named_unit {}; struct electronvolt : named_unit {}; struct gigaelectronvolt : prefixed_unit {}; -struct inverted_gigaelectronvolt : named_unit {}; -struct square_gigaelectronvolt : named_unit {}; +struct inverted_gigaelectronvolt : named_unit {}; +struct square_gigaelectronvolt : named_unit {}; // NOTE: eV as a base unit with no relation to joule prevents us from going back // from natural units to SI. Do we need such a support or should we treat diff --git a/src/include/units/physical/si/angular_velocity.h b/src/include/units/physical/si/angular_velocity.h index a9072ecf..b4825355 100644 --- a/src/include/units/physical/si/angular_velocity.h +++ b/src/include/units/physical/si/angular_velocity.h @@ -30,7 +30,7 @@ namespace units::physical::si { -struct radian_per_second : named_unit {}; +struct radian_per_second : named_unit {}; struct dim_angular_velocity : physical::dim_angular_velocity {}; diff --git a/src/include/units/physical/si/prefixes.h b/src/include/units/physical/si/prefixes.h index e33b45ce..8b0cacc6 100644 --- a/src/include/units/physical/si/prefixes.h +++ b/src/include/units/physical/si/prefixes.h @@ -35,7 +35,7 @@ struct atto : units::prefix struct femto : units::prefix {}; struct pico : units::prefix {}; struct nano : units::prefix {}; -struct micro : units::prefix {}; +struct micro : units::prefix {}; struct milli : units::prefix {}; struct centi : units::prefix {}; struct deci : units::prefix {}; diff --git a/src/include/units/physical/si/resistance.h b/src/include/units/physical/si/resistance.h index f096b0fe..eee8e1cb 100644 --- a/src/include/units/physical/si/resistance.h +++ b/src/include/units/physical/si/resistance.h @@ -30,7 +30,7 @@ namespace units::physical::si { -struct ohm : named_unit {}; +struct ohm : named_unit {}; struct yoctoohm : prefixed_unit {}; struct zeptoohm : prefixed_unit {}; struct attoohm : prefixed_unit {}; diff --git a/src/include/units/quantity.h b/src/include/units/quantity.h index 9e92cf57..06c46c5c 100644 --- a/src/include/units/quantity.h +++ b/src/include/units/quantity.h @@ -28,7 +28,7 @@ #include #include -#if __GNUC__ >= 10 +#if COMP_MSVC || COMP_GCC >= 10 #include #endif @@ -219,7 +219,7 @@ public: // Hidden Friends // Below friend functions are to be found via argument-dependent lookup only -#if __GNUC__ >= 10 +#if COMP_MSVC || COMP_GCC >= 10 template [[nodiscard]] friend constexpr auto operator<=>(const quantity& lhs, const quantity& rhs) diff --git a/src/include/units/quantity_cast.h b/src/include/units/quantity_cast.h index 2d4281b1..14bfbd5b 100644 --- a/src/include/units/quantity_cast.h +++ b/src/include/units/quantity_cast.h @@ -28,6 +28,11 @@ #include #include +#ifdef _MSC_VER +#pragma warning (push) +#pragma warning (disable:4244) // warning C4244: 'argument': conversion from 'intmax_t' to 'T', possible loss of data with T=int +#endif //_MSC_VER + namespace units { constexpr std::intmax_t ipow10(std::intmax_t exp) @@ -77,7 +82,7 @@ struct quantity_cast_impl { template static constexpr To cast(const Q& q) { - return To(static_cast(q.count())); + return To(static_cast(q.count())); } }; @@ -87,13 +92,13 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(static_cast(q.count()) * static_cast(fpow10(CRatio.exp)))); + return To(static_cast(static_cast(q.count()) * static_cast(fpow10(CRatio.exp)))); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(static_cast(q.count()) * static_cast(ipow10(CRatio.exp)))); + return To(static_cast(static_cast(q.count()) * static_cast(ipow10(CRatio.exp)))); } else { - return To(static_cast(static_cast(q.count()) / static_cast(ipow10(-CRatio.exp)))); + return To(static_cast(static_cast(q.count()) / static_cast(ipow10(-CRatio.exp)))); } } } @@ -104,7 +109,7 @@ struct quantity_cast_impl { template static constexpr To cast(const Q& q) { - return To(static_cast(static_cast(q.count()) * + return To(static_cast(static_cast(q.count()) * (static_cast(CRatio.num) / static_cast(CRatio.den)))); } @@ -116,19 +121,19 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(static_cast(q.count()) * + return To(static_cast(static_cast(q.count()) * static_cast(fpow10(CRatio.exp)) * (static_cast(CRatio.num) / static_cast(CRatio.den)))); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(static_cast(q.count()) * + return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) * static_cast(ipow10(CRatio.exp)) / static_cast(CRatio.den))); } else { - return To(static_cast(static_cast(q.count()) * + return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) / (static_cast(CRatio.den) * static_cast(ipow10(-CRatio.exp))))); @@ -142,7 +147,7 @@ struct quantity_cast_impl { template static constexpr To cast(const Q& q) { - return To(static_cast(static_cast(q.count()) / static_cast(CRatio.den))); + return To(static_cast(static_cast(q.count()) / static_cast(CRatio.den))); } }; @@ -152,13 +157,13 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(static_cast(q.count()) * static_cast(fpow10(CRatio.exp)) * (CRep{1} / static_cast(CRatio.den)))); + return To(static_cast(static_cast(q.count()) * static_cast(fpow10(CRatio.exp)) * (CRep{1} / static_cast(CRatio.den)))); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(static_cast(q.count()) * static_cast(ipow10(CRatio.exp)) / static_cast(CRatio.den))); + return To(static_cast(static_cast(q.count()) * static_cast(ipow10(CRatio.exp)) / static_cast(CRatio.den))); } else { - return To(static_cast(static_cast(q.count()) / (static_cast(ipow10(-CRatio.exp)) * static_cast(CRatio.den)))); + return To(static_cast(static_cast(q.count()) / (static_cast(ipow10(-CRatio.exp)) * static_cast(CRatio.den)))); } } } @@ -169,7 +174,7 @@ struct quantity_cast_impl { template static constexpr To cast(const Q& q) { - return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num))); + return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num))); } }; @@ -179,13 +184,13 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) * static_cast(fpow10(CRatio.exp)))); + return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) * static_cast(fpow10(CRatio.exp)))); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) * static_cast(ipow10(CRatio.exp)))); + return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) * static_cast(ipow10(CRatio.exp)))); } else { - return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) / static_cast(ipow10(-CRatio.exp)))); + return To(static_cast(static_cast(q.count()) * static_cast(CRatio.num) / static_cast(ipow10(-CRatio.exp)))); } } } @@ -197,13 +202,13 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(q.count() * fpow10(CRatio.exp))); + return To(static_cast(q.count() * fpow10(CRatio.exp))); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(q.count() * ipow10(CRatio.exp))); + return To(static_cast(q.count() * ipow10(CRatio.exp))); } else { - return To(static_cast(q.count() / ipow10(-CRatio.exp))); + return To(static_cast(q.count() / ipow10(-CRatio.exp))); } } } @@ -214,7 +219,7 @@ struct quantity_cast_impl { template static constexpr To cast(const Q& q) { - return To(static_cast(q.count() * (CRatio.num / CRatio.den))); + return To(static_cast(q.count() * (CRatio.num / CRatio.den))); } }; @@ -224,13 +229,13 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(q.count() * fpow10(CRatio.exp) * (CRatio.num / CRatio.den))); + return To(static_cast(q.count() * fpow10(CRatio.exp) * (CRatio.num / CRatio.den))); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(q.count() * CRatio.num * ipow10(CRatio.exp) / CRatio.den)); + return To(static_cast(q.count() * CRatio.num * ipow10(CRatio.exp) / CRatio.den)); } else { - return To(static_cast(q.count()) * CRatio.num / (CRatio.den * ipow10(-CRatio.exp))); + return To(static_cast(q.count()) * CRatio.num / (CRatio.den * ipow10(-CRatio.exp))); } } } @@ -241,7 +246,7 @@ struct quantity_cast_impl { template static constexpr To cast(const Q& q) { - return To(static_cast(q.count() / CRatio.den)); + return To(static_cast(q.count() / CRatio.den)); } }; @@ -251,13 +256,13 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(q.count() * fpow10(CRatio.exp) / CRatio.den)); + return To(static_cast(q.count() * fpow10(CRatio.exp) / CRatio.den)); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(q.count() * ipow10(CRatio.exp) / CRatio.den)); + return To(static_cast(q.count() * ipow10(CRatio.exp) / CRatio.den)); } else { - return To(static_cast(q.count() / (ipow10(-CRatio.exp) * CRatio.den))); + return To(static_cast(q.count() / (ipow10(-CRatio.exp) * CRatio.den))); } } } @@ -268,7 +273,7 @@ struct quantity_cast_impl { template static constexpr To cast(const Q& q) { - return To(static_cast(q.count() * CRatio.num)); + return To(static_cast(q.count() * CRatio.num)); } }; @@ -278,13 +283,13 @@ struct quantity_cast_impl { static constexpr To cast(const Q& q) { if constexpr (treat_as_floating_point) { - return To(static_cast(q.count() * CRatio.num * fpow10(CRatio.exp))); + return To(static_cast(q.count() * CRatio.num * fpow10(CRatio.exp))); } else { if constexpr (CRatio.exp > 0) { - return To(static_cast(q.count() * CRatio.num * ipow10(CRatio.exp))); + return To(static_cast(q.count() * CRatio.num * ipow10(CRatio.exp))); } else { - return To(static_cast(q.count() * CRatio.num / ipow10(-CRatio.exp))); + return To(static_cast(q.count() * CRatio.num / ipow10(-CRatio.exp))); } } } @@ -413,3 +418,7 @@ template } } // namespace units + +#ifdef _MSC_VER +#pragma warning (pop) +#endif //_MSC_VER diff --git a/src/include/units/quantity_point.h b/src/include/units/quantity_point.h index e0ef8573..863851ba 100644 --- a/src/include/units/quantity_point.h +++ b/src/include/units/quantity_point.h @@ -25,6 +25,10 @@ #include +#if COMP_MSVC || COMP_GCC >= 10 +#include +#endif + namespace units { /** @@ -135,7 +139,7 @@ public: // Hidden Friends // Below friend functions are to be found via argument-dependent lookup only -#if __GNUC__ >= 10 +#if COMP_MSVC || COMP_GCC >= 10 template [[nodiscard]] friend constexpr auto operator<=>(const quantity_point& lhs, const QP& rhs) @@ -201,19 +205,22 @@ public: template quantity_point(quantity) -> quantity_point; -[[nodiscard]] constexpr QuantityPoint AUTO operator+(const QuantityPoint AUTO& lhs, const Quantity AUTO& rhs) +template +[[nodiscard]] constexpr QuantityPoint AUTO operator+(const QP& lhs, const Q& rhs) requires requires { lhs.relative() + rhs; } { return quantity_point(lhs.relative() + rhs); } -[[nodiscard]] constexpr QuantityPoint AUTO operator+(const Quantity AUTO& lhs, const QuantityPoint AUTO& rhs) +template +[[nodiscard]] constexpr QuantityPoint AUTO operator+(const Q& lhs, const QP& rhs) requires requires { rhs + lhs; } { return rhs + lhs; } -[[nodiscard]] constexpr QuantityPoint AUTO operator-(const QuantityPoint AUTO& lhs, const Quantity AUTO& rhs) +template +[[nodiscard]] constexpr QuantityPoint AUTO operator-(const QP& lhs, const Q& rhs) requires requires { lhs.relative() - rhs; } { return quantity_point(lhs.relative() - rhs); diff --git a/src/include/units/random.h b/src/include/units/random.h index 97000502..0ef305f6 100644 --- a/src/include/units/random.h +++ b/src/include/units/random.h @@ -50,7 +50,7 @@ namespace detail { template inline static std::vector fw_bl_pwc(std::initializer_list& bl, UnaryOperation fw) { - using rep = Q::rep; + using rep = TYPENAME Q::rep; std::vector w_bl; w_bl.reserve(bl.size()); for (const Q& qty : bl) { w_bl.push_back(fw(qty)); } @@ -75,8 +75,8 @@ template requires std::integral struct uniform_int_distribution : public std::uniform_int_distribution { - using rep = Q::rep; - using base = std::uniform_int_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::uniform_int_distribution; uniform_int_distribution() : base() {} uniform_int_distribution(const Q& a, const Q& b) : base(a.count(), b.count()) {} @@ -95,8 +95,8 @@ template requires std::floating_point struct uniform_real_distribution : public std::uniform_real_distribution { - using rep = Q::rep; - using base = std::uniform_real_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::uniform_real_distribution; uniform_real_distribution() : base() {} uniform_real_distribution(const Q& a, const Q& b) : base(a.count(), b.count()) {} @@ -115,8 +115,8 @@ template requires std::integral struct binomial_distribution : public std::binomial_distribution { - using rep = Q::rep; - using base = std::binomial_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::binomial_distribution; binomial_distribution() : base() {} binomial_distribution(const Q& t, double p) : base(t.count(), p) {} @@ -134,8 +134,8 @@ template requires std::integral struct negative_binomial_distribution : public std::negative_binomial_distribution { - using rep = Q::rep; - using base = std::negative_binomial_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::negative_binomial_distribution; negative_binomial_distribution() : base() {} negative_binomial_distribution(const Q& k, double p) : base(k.count(), p) {} @@ -153,8 +153,8 @@ template requires std::integral struct geometric_distribution : public std::geometric_distribution { - using rep = Q::rep; - using base = std::geometric_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::geometric_distribution; geometric_distribution() : base() {} geometric_distribution(double p) : base(p) {} @@ -170,8 +170,8 @@ template requires std::integral struct poisson_distribution : public std::poisson_distribution { - using rep = Q::rep; - using base = std::poisson_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::poisson_distribution; poisson_distribution() : base() {} explicit poisson_distribution(double p) : base(p) {} @@ -187,8 +187,8 @@ template requires std::floating_point struct exponential_distribution : public std::exponential_distribution { - using rep = Q::rep; - using base = std::exponential_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::exponential_distribution; exponential_distribution() : base() {} explicit exponential_distribution(const rep& lambda) : base(lambda) {} @@ -204,8 +204,8 @@ template requires std::floating_point struct gamma_distribution : public std::gamma_distribution { - using rep = Q::rep; - using base = std::gamma_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::gamma_distribution; gamma_distribution() : base() {} gamma_distribution(const rep& alpha, const rep& beta) : base(alpha, beta) {} @@ -221,8 +221,8 @@ template requires std::floating_point struct weibull_distribution : public std::weibull_distribution { - using rep = Q::rep; - using base = std::weibull_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::weibull_distribution; weibull_distribution() : base() {} weibull_distribution(const rep& a, const rep& b) : base(a, b) {} @@ -238,8 +238,8 @@ template requires std::floating_point struct extreme_value_distribution : public std::extreme_value_distribution { - using rep = Q::rep; - using base = std::extreme_value_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::extreme_value_distribution; extreme_value_distribution() : base() {} extreme_value_distribution(const Q& a, const rep& b) : base(a.count(), b) {} @@ -257,8 +257,8 @@ template requires std::floating_point struct normal_distribution : public std::normal_distribution { - using rep = Q::rep; - using base = std::normal_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::normal_distribution; normal_distribution() : base() {} normal_distribution(const Q& mean, const Q& stddev) : base(mean.count(), stddev.count()) {} @@ -277,8 +277,8 @@ template requires std::floating_point struct lognormal_distribution : public std::lognormal_distribution { - using rep = Q::rep; - using base = std::lognormal_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::lognormal_distribution; lognormal_distribution() : base() {} lognormal_distribution(const Q& m, const Q& s) : base(m.count(), s.count()) {} @@ -297,8 +297,8 @@ template requires std::floating_point struct chi_squared_distribution : public std::chi_squared_distribution { - using rep = Q::rep; - using base = std::chi_squared_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::chi_squared_distribution; chi_squared_distribution() : base() {} explicit chi_squared_distribution(const rep& n) : base(n) {} @@ -314,8 +314,8 @@ template requires std::floating_point struct cauchy_distribution : public std::cauchy_distribution { - using rep = Q::rep; - using base = std::cauchy_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::cauchy_distribution; cauchy_distribution() : base() {} cauchy_distribution(const Q& a, const Q& b) : base(a.count(), b.count()) {} @@ -334,8 +334,8 @@ template requires std::floating_point struct fisher_f_distribution : public std::fisher_f_distribution { - using rep = Q::rep; - using base = std::fisher_f_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::fisher_f_distribution; fisher_f_distribution() : base() {} fisher_f_distribution(const rep& m, const rep& n) : base(m, n) {} @@ -351,8 +351,8 @@ template requires std::floating_point struct student_t_distribution : public std::student_t_distribution { - using rep = Q::rep; - using base = std::student_t_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::student_t_distribution; student_t_distribution() : base() {} explicit student_t_distribution(const rep& n) : base(n) {} @@ -368,8 +368,8 @@ template requires std::integral struct discrete_distribution : public std::discrete_distribution { - using rep = Q::rep; - using base = std::discrete_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::discrete_distribution; discrete_distribution() : base() {} @@ -393,8 +393,8 @@ template requires std::floating_point class piecewise_constant_distribution : public std::piecewise_constant_distribution { - using rep = Q::rep; - using base = std::piecewise_constant_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::piecewise_constant_distribution; template piecewise_constant_distribution(const std::vector& i, InputIt first_w) : @@ -438,8 +438,8 @@ template requires std::floating_point class piecewise_linear_distribution : public std::piecewise_linear_distribution { - using rep = Q::rep; - using base = std::piecewise_linear_distribution; + using rep = TYPENAME Q::rep; + using base = TYPENAME std::piecewise_linear_distribution; template piecewise_linear_distribution(const std::vector& i, InputIt first_w) : diff --git a/src/include/units/ratio.h b/src/include/units/ratio.h index 6775355b..2a483a46 100644 --- a/src/include/units/ratio.h +++ b/src/include/units/ratio.h @@ -53,7 +53,7 @@ struct ratio { detail::normalize(num, den, exp); } -#if __GNUC__ >= 10 +#if COMP_MSVC || COMP_GCC >= 10 [[nodiscard]] friend constexpr bool operator==(const ratio&, const ratio&) = default; diff --git a/src/include/units/symbol_text.h b/src/include/units/symbol_text.h index 6114d11b..131979ac 100644 --- a/src/include/units/symbol_text.h +++ b/src/include/units/symbol_text.h @@ -26,7 +26,7 @@ #include #include -#if COMP_GCC >= 10 +#if COMP_MSVC || COMP_GCC >= 10 #include #endif @@ -125,7 +125,7 @@ struct basic_symbol_text { return basic_symbol_text(lhs) + rhs; } -#if COMP_GCC >= 10 +#if COMP_MSVC || COMP_GCC >= 10 template [[nodiscard]] friend constexpr auto operator<=>(const basic_symbol_text& lhs, diff --git a/test/metabench/make_dimension/type_traits.h b/test/metabench/make_dimension/type_traits.h index 4a9c8a50..842410f3 100644 --- a/test/metabench/make_dimension/type_traits.h +++ b/test/metabench/make_dimension/type_traits.h @@ -43,6 +43,6 @@ namespace units { } template - using conditional = detail::conditional_impl::template type; + using conditional = TYPENAME detail::conditional_impl::template type; } diff --git a/test/unit_test/runtime/CMakeLists.txt b/test/unit_test/runtime/CMakeLists.txt index 9ed02737..0a727dbb 100644 --- a/test/unit_test/runtime/CMakeLists.txt +++ b/test/unit_test/runtime/CMakeLists.txt @@ -37,5 +37,12 @@ target_link_libraries(unit_tests_runtime $,CONAN_PKG::catch2,Catch2::Catch2> ) +if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + target_compile_options(unit_tests_runtime + PRIVATE + /wd4244 # 'conversion' conversion from 'type1' to 'type2', possible loss of data + ) +endif() + include(Catch) catch_discover_tests(unit_tests_runtime) diff --git a/test/unit_test/static/dimension_op_test.cpp b/test/unit_test/static/dimension_op_test.cpp index b96daafc..dff74f2c 100644 --- a/test/unit_test/static/dimension_op_test.cpp +++ b/test/unit_test/static/dimension_op_test.cpp @@ -48,7 +48,7 @@ template struct typeinfo; template -using dim_unpack = detail::dim_unpack::type; +using dim_unpack = TYPENAME detail::dim_unpack::type; template using derived_dim = detail::derived_dimension_base; diff --git a/test/unit_test/static/quantity_point_test.cpp b/test/unit_test/static/quantity_point_test.cpp index ba5d3aa0..424d785f 100644 --- a/test/unit_test/static/quantity_point_test.cpp +++ b/test/unit_test/static/quantity_point_test.cpp @@ -226,7 +226,7 @@ static_assert(quantity_point_cast(quantity_point(1.23q_m)).relative().count // time -#if __GNUC__ >= 10 +#if COMP_MSVC || COMP_GCC >= 10 static_assert(!std::equality_comparable_with, quantity_point>); // different dimensions #endif diff --git a/test/unit_test/static/si_fps_test.cpp b/test/unit_test/static/si_fps_test.cpp index 49435b1a..bdbc57af 100644 --- a/test/unit_test/static/si_fps_test.cpp +++ b/test/unit_test/static/si_fps_test.cpp @@ -142,7 +142,8 @@ static_assert(quantity_cast>(si::length(0.3048 // static_assert(1q_ft - si::length(1) == -si::length(0.6952)); // should not compile (different dimensions) // static_assert(si::length(1) - 1q_ft == si::length(0.6952)); // should not compile (different dimensions) -static_assert(quantity_cast>(6.q_ft) - si::length(1) == si::length(0.8288)); // 6 ft in m - 1 m = ... m +static_assert(quantity_cast>(6.q_ft) - si::length(1) > si::length(0.8287) && + quantity_cast>(6.q_ft) - si::length(1) < si::length(0.8289)); // 6 ft in m - 1 m = ... m static_assert(si::length(5) - quantity_cast>(6q_ft) == si::length(3.1712)); // 5 m - 6 ft in m = ... static_assert(6.q_ft - quantity_cast>(si::length(0.3048)) == 5.q_ft); // 6 ft - 1 ft in m = 5 ft static_assert(quantity_cast>(si::length(1.8288)) - 1.q_ft == 5.q_ft); // 6 ft in m - 1 ft = 5 ft diff --git a/test/unit_test/static/symbol_text_test.cpp b/test/unit_test/static/symbol_text_test.cpp index e50f7443..bdc2b42a 100644 --- a/test/unit_test/static/symbol_text_test.cpp +++ b/test/unit_test/static/symbol_text_test.cpp @@ -36,8 +36,8 @@ static_assert(sym1 <= 'b'); static_assert(sym1 <= 'c'); static_assert(sym1 >= 'b'); static_assert(sym1 >= 'a'); -static_assert(sym1.standard() == 'b'); -static_assert(sym1.ascii() == 'b'); +static_assert(sym1.standard() == "b"); +static_assert(sym1.ascii() == "b"); constexpr basic_symbol_text sym2('a', 'b'); static_assert(sym2 == basic_symbol_text('a', 'b')); @@ -59,7 +59,7 @@ static_assert(sym5.standard() == "bc"); static_assert(sym5.ascii() == "de"); constexpr basic_fixed_string txt2("de"); -constexpr basic_symbol_text sym6(txt1, txt2); +constexpr basic_symbol_text sym6(sym4.standard(), txt2); static_assert(sym6.standard() == "bc"); static_assert(sym6.ascii() == "de");