VS2019 support added

This commit is contained in:
Mateusz Pusz
2020-09-04 23:00:57 +02:00
parent 71e3dba69a
commit b318e8d039
38 changed files with 253 additions and 160 deletions

View File

@ -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):

View File

@ -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;
// ...
};

View File

@ -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()

View File

@ -28,6 +28,10 @@
#include <array>
#include <iostream>
#if COMP_MSVC || COMP_GCC >= 10
#include <compare>
#endif
// horizontal/vertical vector
namespace {
@ -70,7 +74,7 @@ public:
return *this;
}
#if __GNUC__ >= 10
#if COMP_MSVC || COMP_GCC >= 10
template<typename Q2>
[[nodiscard]] friend constexpr auto operator<=>(const vector& lhs, const vector<Q2, D>& rhs)

View File

@ -24,6 +24,10 @@
#include <cmath>
#include <iostream>
#if COMP_MSVC || COMP_GCC >= 10
#include <compare>
#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

View File

@ -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")
$<IF:$<TARGET_EXISTS:CONAN_PKG::range-v3>,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

View File

@ -67,7 +67,7 @@ quantity_point<D, U, Rep> common_quantity_point_impl(quantity<D, U, Rep>);
template<Quantity Q1, Quantity Q2, Scalar Rep = std::common_type_t<typename Q1::rep, typename Q2::rep>>
requires equivalent_dim<typename Q1::dimension, typename Q2::dimension>
using common_quantity = detail::common_quantity_impl<Q1, Q2, Rep>::type;
using common_quantity = TYPENAME detail::common_quantity_impl<Q1, Q2, Rep>::type;
template<QuantityPoint QP1, QuantityPoint QP2>
requires requires { typename common_quantity<typename QP1::quantity_type, typename QP2::quantity_type>; }
@ -76,7 +76,7 @@ using common_quantity_point = decltype(
} // namespace units
#if COMP_GCC >= 10
#if COMP_MSVC || COMP_GCC >= 10
namespace std {

View File

@ -48,7 +48,7 @@ struct dim_unpack<exp<Dim, Num, Den>, ERest...> {
template<DerivedDimension Dim, std::intmax_t Num, std::intmax_t Den, Exponent... ERest>
struct dim_unpack<exp<Dim, Num, Den>, ERest...> {
using type = dim_unpack<exp<downcast_base_t<Dim>, Num, Den>, ERest...>::type;
using type = TYPENAME dim_unpack<exp<downcast_base_t<Dim>, Num, Den>, ERest...>::type;
};
template<Exponent... Es, std::intmax_t Num, std::intmax_t Den, Exponent... ERest>

View File

@ -97,13 +97,13 @@ struct downcast_dimension_impl<D> {
template<DerivedDimension D>
struct downcast_dimension_impl<D> {
using type = check_unknown<downcast<D>>::type;
using type = TYPENAME check_unknown<downcast<D>>::type;
};
} // namespace detail
template<Dimension D>
using downcast_dimension = detail::downcast_dimension_impl<D>::type;
using downcast_dimension = TYPENAME detail::downcast_dimension_impl<D>::type;
// dim_invert
namespace detail {
@ -133,7 +133,7 @@ struct dim_invert_impl<D> : dim_invert_impl<downcast_base_t<D>> {
} // namespace detail
template<Dimension D>
using dim_invert = detail::dim_invert_impl<D>::type;
using dim_invert = TYPENAME detail::dim_invert_impl<D>::type;
// dimension_multiply
namespace detail {
@ -161,7 +161,7 @@ struct to_dimension<exp_list<exp<D, 1>>> {
* dimension itself.
*/
template<Dimension D1, Dimension D2>
using merge_dimension = to_dimension<typename dim_consolidate<type_list_merge_sorted<typename D1::exponents, typename D2::exponents, exp_less>>::type>::type;
using merge_dimension = TYPENAME to_dimension<typename dim_consolidate<type_list_merge_sorted<typename D1::exponents, typename D2::exponents, exp_less>>::type>::type;
template<Dimension D1, Dimension D2>
struct dimension_multiply_impl;
@ -178,7 +178,7 @@ struct dimension_multiply_impl<D1, D2> {
template<DerivedDimension D1, BaseDimension D2>
struct dimension_multiply_impl<D1, D2> {
using type = dimension_multiply_impl<D2, D1>::type;
using type = TYPENAME dimension_multiply_impl<D2, D1>::type;
};
template<DerivedDimension D1, DerivedDimension D2>
@ -189,10 +189,10 @@ struct dimension_multiply_impl<D1, D2> {
} // namespace detail
template<Dimension D1, Dimension D2>
using dimension_multiply = detail::dimension_multiply_impl<D1, D2>::type;
using dimension_multiply = TYPENAME detail::dimension_multiply_impl<D1, D2>::type;
template<Dimension D1, Dimension D2>
using dimension_divide = detail::dimension_multiply_impl<D1, dim_invert<D2>>::type;
using dimension_divide = TYPENAME detail::dimension_multiply_impl<D1, dim_invert<D2>>::type;
// dimension_sqrt
namespace detail {
@ -212,7 +212,7 @@ struct dimension_sqrt_impl<derived_dimension_base<exp<D, 2>>> {
template<DerivedDimension D>
struct dimension_sqrt_impl<D> {
using type = dimension_sqrt_impl<typename D::downcast_base_type>::type;
using type = TYPENAME dimension_sqrt_impl<typename D::downcast_base_type>::type;
};
template<typename... Es>
@ -223,7 +223,7 @@ struct dimension_sqrt_impl<derived_dimension_base<Es...>> {
} // namespace detail
template<Dimension D>
using dimension_sqrt = detail::dimension_sqrt_impl<D>::type;
using dimension_sqrt = TYPENAME detail::dimension_sqrt_impl<D>::type;
// dimension_pow
namespace detail {
@ -248,7 +248,7 @@ struct dimension_pow_impl<derived_dimension_base<exp<D, 1, N>>, N> {
template<DerivedDimension D, std::intmax_t N>
struct dimension_pow_impl<D, N> {
using type = dimension_pow_impl<downcast_base_t<D>, N>::type;
using type = TYPENAME dimension_pow_impl<downcast_base_t<D>, N>::type;
};
template<typename... Es, std::intmax_t N>
@ -259,6 +259,6 @@ struct dimension_pow_impl<derived_dimension_base<Es...>, N> {
} // namespace detail
template<Dimension D, std::intmax_t N>
using dimension_pow = detail::dimension_pow_impl<D, N>::type;
using dimension_pow = TYPENAME detail::dimension_pow_impl<D, N>::type;
} // namespace units

View File

@ -68,6 +68,6 @@ template<Downcastable T>
using downcast = decltype(detail::downcast_impl<T>());
template<Downcastable T>
using downcast_base_t = T::downcast_base_type;
using downcast_base_t = TYPENAME T::downcast_base_type;
} // namespace units

View File

@ -22,9 +22,15 @@
#pragma once
#include <units/bits/external/hacks.h>
#include <algorithm>
#include <cstdlib>
#include <ostream>
#if COMP_MSVC || COMP_GCC >= 10
#include <compare>
#endif
namespace units {
/**
@ -70,20 +76,20 @@ struct basic_fixed_string {
return basic_fixed_string<CharT, N + N2>(txt);
}
#if __GNUC__ >= 10
#if COMP_MSVC || COMP_GCC >= 10
template<typename CharT2, std::size_t N2>
[[nodiscard]] friend constexpr auto operator<=>(const basic_fixed_string& lhs,
const basic_fixed_string<CharT2, N2>& 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<typename CharT2, std::size_t N2>
[[nodiscard]] friend constexpr bool operator==(const basic_fixed_string& lhs,
const basic_fixed_string<CharT2, N2>& rhs)
template<std::size_t N2>
[[nodiscard]] friend constexpr bool operator==(const basic_fixed_string&, const basic_fixed_string<CharT, N2>&) { return false; }
template<std::size_t N2>
[[nodiscard]] friend constexpr auto operator<=>(const basic_fixed_string& lhs, const basic_fixed_string<CharT, N2>& 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

View File

@ -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 <concepts>
@ -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<T>
@ -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<class T>
@ -100,5 +113,6 @@ namespace std {
concept regular_invocable = invocable<F, Args...>;
#endif
#endif
} // namespace std

View File

@ -24,6 +24,11 @@
#include <units/bits/external/type_traits.h>
#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<List<OldTypes...>, NewTypes...> {
} // namespace detail
template<TypeList List, typename... Types>
using type_list_push_front = detail::type_list_push_front_impl<List, Types...>::type;
using type_list_push_front = TYPENAME detail::type_list_push_front_impl<List, Types...>::type;
// push_back
@ -71,7 +76,7 @@ struct type_list_push_back_impl<List<OldTypes...>, NewTypes...> {
} // namespace detail
template<TypeList List, typename... Types>
using type_list_push_back = detail::type_list_push_back_impl<List, Types...>::type;
using type_list_push_back = TYPENAME detail::type_list_push_back_impl<List, Types...>::type;
// join
@ -84,13 +89,13 @@ struct type_list_join_impl {
template<template<typename...> typename List, typename... First, typename... Second, typename... Rest>
struct type_list_join_impl<List<First...>, List<Second...>, Rest...> {
using type = type_list_join_impl<List<First..., Second...>, Rest...>::type;
using type = TYPENAME type_list_join_impl<List<First..., Second...>, Rest...>::type;
};
} // namespace detail
template<TypeList... Lists>
using type_list_join = detail::type_list_join_impl<Lists...>::type;
using type_list_join = TYPENAME detail::type_list_join_impl<Lists...>::type;
// split
@ -125,8 +130,8 @@ template<template<typename...> typename List, std::size_t N, typename... Types>
struct type_list_split<List<Types...>, N> {
static_assert(N <= sizeof...(Types), "Invalid index provided");
using split = detail::split_impl<List, 0, N, Types...>;
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<Lhs1, LhsRest...>, List<Rhs1, RhsRest...
} // namespace detail
template<TypeList SortedList1, TypeList SortedList2, template<typename, typename> typename Pred>
using type_list_merge_sorted = detail::type_list_merge_sorted_impl<SortedList1, SortedList2, Pred>::type;
using type_list_merge_sorted = TYPENAME detail::type_list_merge_sorted_impl<SortedList1, SortedList2, Pred>::type;
// sort
@ -192,14 +197,18 @@ template<template<typename...> typename List, typename... Types, template<typena
struct type_list_sort_impl<List<Types...>, Pred> {
using types = List<Types...>;
using split = type_list_split_half<List<Types...>>;
using sorted_left = type_list_sort_impl<typename split::first_list, Pred>::type;
using sorted_right = type_list_sort_impl<typename split::second_list, Pred>::type;
using type = type_list_merge_sorted_impl<sorted_left, sorted_right, Pred>::type;
using sorted_left = TYPENAME type_list_sort_impl<typename split::first_list, Pred>::type;
using sorted_right = TYPENAME type_list_sort_impl<typename split::second_list, Pred>::type;
using type = TYPENAME type_list_merge_sorted_impl<sorted_left, sorted_right, Pred>::type;
};
} // namespace detail
template<TypeList List, template<typename, typename> typename Pred>
using type_list_sort = detail::type_list_sort_impl<List, Pred>::type;
using type_list_sort = TYPENAME detail::type_list_sort_impl<List, Pred>::type;
} // namespace units
#ifdef _MSC_VER
#pragma warning (pop)
#endif //_MSC_VER

View File

@ -22,6 +22,7 @@
#pragma once
#include <units/bits/external/hacks.h>
#include <type_traits>
namespace units {
@ -44,7 +45,7 @@ struct conditional_impl<true> {
} // namespace detail
template<bool B, typename T, typename F>
using conditional = detail::conditional_impl<B>::template type<T, F>;
using conditional = TYPENAME detail::conditional_impl<B>::template type<T, F>;
// is_same
template<class T, class U>

View File

@ -24,6 +24,7 @@
#include <units/bits/external/hacks.h>
#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>
#include <cstdint>

View File

@ -113,12 +113,12 @@ constexpr auto exp_list_with_named_units(exp_list<Es...>);
template<Exponent Exp>
constexpr auto exp_list_with_named_units(Exp)
{
using dim = Exp::dimension;
using dim = TYPENAME Exp::dimension;
if constexpr(dimension_unit<dim>::is_named) {
return exp_list<Exp>();
}
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<Es...>)
template<Dimension Dim>
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()));
}

View File

@ -174,12 +174,12 @@ struct dimension_unit_impl;
template<BaseDimension D>
struct dimension_unit_impl<D> {
using type = D::base_unit;
using type = TYPENAME D::base_unit;
};
template<DerivedDimension D>
struct dimension_unit_impl<D> {
using type = D::coherent_unit;
using type = TYPENAME D::coherent_unit;
};
} // namespace detail
@ -193,7 +193,7 @@ struct dimension_unit_impl<D> {
* @tparam D Dimension type to get the unit from.
*/
template<Dimension D>
using dimension_unit = detail::dimension_unit_impl<D>::type;
using dimension_unit = TYPENAME detail::dimension_unit_impl<D>::type;
/**
* @brief A concept matching only units of a specified dimension.

View File

@ -46,7 +46,7 @@ namespace detail {
* this base dimension.
*/
template<Exponent... Es>
using make_dimension = to_derived_dimension_base<typename dim_consolidate<type_list_sort<typename dim_unpack<Es...>::type, exp_less>>::type>::type;
using make_dimension = TYPENAME to_derived_dimension_base<typename dim_consolidate<type_list_sort<typename dim_unpack<Es...>::type, exp_less>>::type>::type;
} // namespace detail

View File

@ -77,7 +77,7 @@ struct exp_multiply_impl {
} // namespace detail
template<Exponent E, std::intmax_t Num, std::intmax_t Den>
using exp_multiply = detail::exp_multiply_impl<E, Num, Den>::type;
using exp_multiply = TYPENAME detail::exp_multiply_impl<E, Num, Den>::type;
template<Exponent... Es>
struct exp_list {};

View File

@ -24,9 +24,19 @@
#include <units/customization_points.h>
#include <units/quantity.h>
#include <fmt/format.h>
#include <string_view>
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable:4702) // C4702: unreachable code
#endif //_MSC_VER
#include <fmt/format.h>
#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<Dimension, Unit>();
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<typename Dimension, typename Unit, typename Rep, typename CharT>
struct fmt::formatter<units::quantity<Dimension, Unit, Rep>, CharT> {
private:
using quantity = units::quantity<Dimension, Unit, Rep>;
using iterator = fmt::basic_format_parse_context<CharT>::iterator;
using iterator = TYPENAME fmt::basic_format_parse_context<CharT>::iterator;
using arg_ref_type = fmt::detail::arg_ref<CharT>;
units::detail::global_format_specs<CharT> global_specs;

View File

@ -45,7 +45,7 @@ inline Quantity AUTO pow(const Q& q) noexcept
{
using dim = dimension_pow<typename Q::dimension, N>;
using unit = downcast_unit<dim, pow<N>(Q::unit::ratio)>;
using rep = Q::rep;
using rep = TYPENAME Q::rep;
return quantity<dim, unit, rep>(static_cast<rep>(std::pow(q.count(), N)));
}
@ -56,7 +56,7 @@ inline Quantity AUTO pow(const Q& q) noexcept
*/
template<std::intmax_t N, Quantity Q>
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<typename Q::dimension>;
using unit = downcast_unit<dim, sqrt(Q::unit::ratio)>;
using rep = Q::rep;
using rep = TYPENAME Q::rep;
return quantity<dim, unit, rep>(static_cast<rep>(std::sqrt(q.count())));
}

View File

@ -30,8 +30,8 @@ namespace units::physical::natural {
struct unitless : named_unit<unitless, "", no_prefix> {};
struct electronvolt : named_unit<electronvolt, "eV", si::prefix> {};
struct gigaelectronvolt : prefixed_unit<gigaelectronvolt, si::giga, electronvolt> {};
struct inverted_gigaelectronvolt : named_unit<inverted_gigaelectronvolt, {"GeV⁻¹", "GeV^-1"}, no_prefix> {};
struct square_gigaelectronvolt : named_unit<square_gigaelectronvolt, {"GeV²", "GeV^2"}, no_prefix> {};
struct inverted_gigaelectronvolt : named_unit<inverted_gigaelectronvolt, basic_symbol_text{"GeV⁻¹", "GeV^-1"}, no_prefix> {};
struct square_gigaelectronvolt : named_unit<square_gigaelectronvolt, basic_symbol_text{"GeV²", "GeV^2"}, no_prefix> {};
// 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

View File

@ -30,7 +30,7 @@
namespace units::physical::si {
struct radian_per_second : named_unit<radian_per_second, {"ω", "w"}, no_prefix> {};
struct radian_per_second : named_unit<radian_per_second, basic_symbol_text{"ω", "w"}, no_prefix> {};
struct dim_angular_velocity : physical::dim_angular_velocity<dim_angular_velocity, radian_per_second, dim_angle, dim_time> {};

View File

@ -35,7 +35,7 @@ struct atto : units::prefix<atto, prefix, "a", ratio(1, 1, -18)>
struct femto : units::prefix<femto, prefix, "f", ratio(1, 1, -15)> {};
struct pico : units::prefix<pico, prefix, "p", ratio(1, 1, -12)> {};
struct nano : units::prefix<nano, prefix, "n", ratio(1, 1, -9)> {};
struct micro : units::prefix<micro, prefix, {"\u00b5", "u"}, ratio(1, 1, -6)> {};
struct micro : units::prefix<micro, prefix, basic_symbol_text{"\u00b5", "u"}, ratio(1, 1, -6)> {};
struct milli : units::prefix<milli, prefix, "m", ratio(1, 1, -3)> {};
struct centi : units::prefix<centi, prefix, "c", ratio(1, 1, -2)> {};
struct deci : units::prefix<deci, prefix, "d", ratio(1, 1, -1)> {};

View File

@ -30,7 +30,7 @@
namespace units::physical::si {
struct ohm : named_unit<ohm, {"Ω", "ohm"}, prefix> {};
struct ohm : named_unit<ohm, basic_symbol_text{"Ω", "ohm"}, prefix> {};
struct yoctoohm : prefixed_unit<yoctoohm, yocto, ohm> {};
struct zeptoohm : prefixed_unit<zeptoohm, zepto, ohm> {};
struct attoohm : prefixed_unit<attoohm, atto, ohm> {};

View File

@ -28,7 +28,7 @@
#include <units/bits/to_string.h>
#include <units/quantity_cast.h>
#if __GNUC__ >= 10
#if COMP_MSVC || COMP_GCC >= 10
#include <compare>
#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<typename D2, typename U2, typename Rep2>
[[nodiscard]] friend constexpr auto operator<=>(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)

View File

@ -28,6 +28,11 @@
#include <units/bits/external/type_traits.h>
#include <cassert>
#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<To, CRatio, CRep, true, true, true> {
template<Quantity Q>
static constexpr To cast(const Q& q)
{
return To(static_cast<To::rep>(q.count()));
return To(static_cast<TYPENAME To::rep>(q.count()));
}
};
@ -87,13 +92,13 @@ struct quantity_cast_impl<To, CRatio, CRep, true, true, false> {
static constexpr To cast(const Q& q)
{
if constexpr (treat_as_floating_point<CRep>) {
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(fpow10<CRep>(CRatio.exp))));
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(fpow10<CRep>(CRatio.exp))));
} else {
if constexpr (CRatio.exp > 0) {
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(ipow10(CRatio.exp))));
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(ipow10(CRatio.exp))));
}
else {
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) / static_cast<CRep>(ipow10(-CRatio.exp))));
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) / static_cast<CRep>(ipow10(-CRatio.exp))));
}
}
}
@ -104,7 +109,7 @@ struct quantity_cast_impl<To, CRatio, CRep, false, false, true> {
template<typename Q>
static constexpr To cast(const Q& q)
{
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) *
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) *
(static_cast<CRep>(CRatio.num) /
static_cast<CRep>(CRatio.den))));
}
@ -116,19 +121,19 @@ struct quantity_cast_impl<To, CRatio, CRep, false, false, false> {
static constexpr To cast(const Q& q)
{
if constexpr (treat_as_floating_point<CRep>) {
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) *
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) *
static_cast<CRep>(fpow10<CRep>(CRatio.exp)) *
(static_cast<CRep>(CRatio.num) /
static_cast<CRep>(CRatio.den))));
} else {
if constexpr (CRatio.exp > 0) {
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) *
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) *
static_cast<CRep>(CRatio.num) *
static_cast<CRep>(ipow10(CRatio.exp)) /
static_cast<CRep>(CRatio.den)));
}
else {
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) *
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) *
static_cast<CRep>(CRatio.num) /
(static_cast<CRep>(CRatio.den) *
static_cast<CRep>(ipow10(-CRatio.exp)))));
@ -142,7 +147,7 @@ struct quantity_cast_impl<To, CRatio, CRep, true, false, true> {
template<Quantity Q>
static constexpr To cast(const Q& q)
{
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) / static_cast<CRep>(CRatio.den)));
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) / static_cast<CRep>(CRatio.den)));
}
};
@ -152,13 +157,13 @@ struct quantity_cast_impl<To, CRatio, CRep, true, false, false> {
static constexpr To cast(const Q& q)
{
if constexpr (treat_as_floating_point<CRep>) {
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(fpow10<CRep>(CRatio.exp)) * (CRep{1} / static_cast<CRep>(CRatio.den))));
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(fpow10<CRep>(CRatio.exp)) * (CRep{1} / static_cast<CRep>(CRatio.den))));
} else {
if constexpr (CRatio.exp > 0) {
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(ipow10(CRatio.exp)) / static_cast<CRep>(CRatio.den)));
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(ipow10(CRatio.exp)) / static_cast<CRep>(CRatio.den)));
}
else {
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) / (static_cast<CRep>(ipow10(-CRatio.exp)) * static_cast<CRep>(CRatio.den))));
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) / (static_cast<CRep>(ipow10(-CRatio.exp)) * static_cast<CRep>(CRatio.den))));
}
}
}
@ -169,7 +174,7 @@ struct quantity_cast_impl<To, CRatio, CRep, false, true, true> {
template<Quantity Q>
static constexpr To cast(const Q& q)
{
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num)));
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num)));
}
};
@ -179,13 +184,13 @@ struct quantity_cast_impl<To, CRatio, CRep, false, true, false> {
static constexpr To cast(const Q& q)
{
if constexpr (treat_as_floating_point<CRep>) {
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num) * static_cast<CRep>(fpow10<CRep>(CRatio.exp))));
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num) * static_cast<CRep>(fpow10<CRep>(CRatio.exp))));
} else {
if constexpr (CRatio.exp > 0) {
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num) * static_cast<CRep>(ipow10(CRatio.exp))));
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num) * static_cast<CRep>(ipow10(CRatio.exp))));
}
else {
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num) / static_cast<CRep>(ipow10(-CRatio.exp))));
return To(static_cast<TYPENAME To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio.num) / static_cast<CRep>(ipow10(-CRatio.exp))));
}
}
}
@ -197,13 +202,13 @@ struct quantity_cast_impl<To, CRatio, CRep, true, true, false> {
static constexpr To cast(const Q& q)
{
if constexpr (treat_as_floating_point<CRep>) {
return To(static_cast<To::rep>(q.count() * fpow10<CRep>(CRatio.exp)));
return To(static_cast<TYPENAME To::rep>(q.count() * fpow10<CRep>(CRatio.exp)));
} else {
if constexpr (CRatio.exp > 0) {
return To(static_cast<To::rep>(q.count() * ipow10(CRatio.exp)));
return To(static_cast<TYPENAME To::rep>(q.count() * ipow10(CRatio.exp)));
}
else {
return To(static_cast<To::rep>(q.count() / ipow10(-CRatio.exp)));
return To(static_cast<TYPENAME To::rep>(q.count() / ipow10(-CRatio.exp)));
}
}
}
@ -214,7 +219,7 @@ struct quantity_cast_impl<To, CRatio, CRep, false, false, true> {
template<typename Q>
static constexpr To cast(const Q& q)
{
return To(static_cast<To::rep>(q.count() * (CRatio.num / CRatio.den)));
return To(static_cast<TYPENAME To::rep>(q.count() * (CRatio.num / CRatio.den)));
}
};
@ -224,13 +229,13 @@ struct quantity_cast_impl<To, CRatio, CRep, false, false, false> {
static constexpr To cast(const Q& q)
{
if constexpr (treat_as_floating_point<CRep>) {
return To(static_cast<To::rep>(q.count() * fpow10<CRep>(CRatio.exp) * (CRatio.num / CRatio.den)));
return To(static_cast<TYPENAME To::rep>(q.count() * fpow10<CRep>(CRatio.exp) * (CRatio.num / CRatio.den)));
} else {
if constexpr (CRatio.exp > 0) {
return To(static_cast<To::rep>(q.count() * CRatio.num * ipow10(CRatio.exp) / CRatio.den));
return To(static_cast<TYPENAME To::rep>(q.count() * CRatio.num * ipow10(CRatio.exp) / CRatio.den));
}
else {
return To(static_cast<To::rep>(q.count()) * CRatio.num / (CRatio.den * ipow10(-CRatio.exp)));
return To(static_cast<TYPENAME To::rep>(q.count()) * CRatio.num / (CRatio.den * ipow10(-CRatio.exp)));
}
}
}
@ -241,7 +246,7 @@ struct quantity_cast_impl<To, CRatio, CRep, true, false, true> {
template<Quantity Q>
static constexpr To cast(const Q& q)
{
return To(static_cast<To::rep>(q.count() / CRatio.den));
return To(static_cast<TYPENAME To::rep>(q.count() / CRatio.den));
}
};
@ -251,13 +256,13 @@ struct quantity_cast_impl<To, CRatio, CRep, true, false, false> {
static constexpr To cast(const Q& q)
{
if constexpr (treat_as_floating_point<CRep>) {
return To(static_cast<To::rep>(q.count() * fpow10<CRep>(CRatio.exp) / CRatio.den));
return To(static_cast<TYPENAME To::rep>(q.count() * fpow10<CRep>(CRatio.exp) / CRatio.den));
} else {
if constexpr (CRatio.exp > 0) {
return To(static_cast<To::rep>(q.count() * ipow10(CRatio.exp) / CRatio.den));
return To(static_cast<TYPENAME To::rep>(q.count() * ipow10(CRatio.exp) / CRatio.den));
}
else {
return To(static_cast<To::rep>(q.count() / (ipow10(-CRatio.exp) * CRatio.den)));
return To(static_cast<TYPENAME To::rep>(q.count() / (ipow10(-CRatio.exp) * CRatio.den)));
}
}
}
@ -268,7 +273,7 @@ struct quantity_cast_impl<To, CRatio, CRep, false, true, true> {
template<Quantity Q>
static constexpr To cast(const Q& q)
{
return To(static_cast<To::rep>(q.count() * CRatio.num));
return To(static_cast<TYPENAME To::rep>(q.count() * CRatio.num));
}
};
@ -278,13 +283,13 @@ struct quantity_cast_impl<To, CRatio, CRep, false, true, false> {
static constexpr To cast(const Q& q)
{
if constexpr (treat_as_floating_point<CRep>) {
return To(static_cast<To::rep>(q.count() * CRatio.num * fpow10<CRep>(CRatio.exp)));
return To(static_cast<TYPENAME To::rep>(q.count() * CRatio.num * fpow10<CRep>(CRatio.exp)));
} else {
if constexpr (CRatio.exp > 0) {
return To(static_cast<To::rep>(q.count() * CRatio.num * ipow10(CRatio.exp)));
return To(static_cast<TYPENAME To::rep>(q.count() * CRatio.num * ipow10(CRatio.exp)));
}
else {
return To(static_cast<To::rep>(q.count() * CRatio.num / ipow10(-CRatio.exp)));
return To(static_cast<TYPENAME To::rep>(q.count() * CRatio.num / ipow10(-CRatio.exp)));
}
}
}
@ -413,3 +418,7 @@ template<typename CastSpec, typename D, typename U, typename Rep>
}
} // namespace units
#ifdef _MSC_VER
#pragma warning (pop)
#endif //_MSC_VER

View File

@ -25,6 +25,10 @@
#include <units/quantity.h>
#if COMP_MSVC || COMP_GCC >= 10
#include <compare>
#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<QuantityPoint QP>
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point& lhs, const QP& rhs)
@ -201,19 +205,22 @@ public:
template<typename D, typename U, typename Rep>
quantity_point(quantity<D, U, Rep>) -> quantity_point<D, U, Rep>;
[[nodiscard]] constexpr QuantityPoint AUTO operator+(const QuantityPoint AUTO& lhs, const Quantity AUTO& rhs)
template<QuantityPoint QP, Quantity Q>
[[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<Quantity Q, QuantityPoint QP>
[[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<QuantityPoint QP, Quantity Q>
[[nodiscard]] constexpr QuantityPoint AUTO operator-(const QP& lhs, const Q& rhs)
requires requires { lhs.relative() - rhs; }
{
return quantity_point(lhs.relative() - rhs);

View File

@ -50,7 +50,7 @@ namespace detail {
template <Quantity Q, typename UnaryOperation>
inline static std::vector<typename Q::rep> fw_bl_pwc(std::initializer_list<Q>& bl, UnaryOperation fw)
{
using rep = Q::rep;
using rep = TYPENAME Q::rep;
std::vector<rep> w_bl;
w_bl.reserve(bl.size());
for (const Q& qty : bl) { w_bl.push_back(fw(qty)); }
@ -75,8 +75,8 @@ template<Quantity Q>
requires std::integral<typename Q::rep>
struct uniform_int_distribution : public std::uniform_int_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::uniform_int_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::uniform_int_distribution<rep>;
uniform_int_distribution() : base() {}
uniform_int_distribution(const Q& a, const Q& b) : base(a.count(), b.count()) {}
@ -95,8 +95,8 @@ template<Quantity Q>
requires std::floating_point<typename Q::rep>
struct uniform_real_distribution : public std::uniform_real_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::uniform_real_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::uniform_real_distribution<rep>;
uniform_real_distribution() : base() {}
uniform_real_distribution(const Q& a, const Q& b) : base(a.count(), b.count()) {}
@ -115,8 +115,8 @@ template<Quantity Q>
requires std::integral<typename Q::rep>
struct binomial_distribution : public std::binomial_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::binomial_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::binomial_distribution<rep>;
binomial_distribution() : base() {}
binomial_distribution(const Q& t, double p) : base(t.count(), p) {}
@ -134,8 +134,8 @@ template<Quantity Q>
requires std::integral<typename Q::rep>
struct negative_binomial_distribution : public std::negative_binomial_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::negative_binomial_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::negative_binomial_distribution<rep>;
negative_binomial_distribution() : base() {}
negative_binomial_distribution(const Q& k, double p) : base(k.count(), p) {}
@ -153,8 +153,8 @@ template<Quantity Q>
requires std::integral<typename Q::rep>
struct geometric_distribution : public std::geometric_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::geometric_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::geometric_distribution<rep>;
geometric_distribution() : base() {}
geometric_distribution(double p) : base(p) {}
@ -170,8 +170,8 @@ template<Quantity Q>
requires std::integral<typename Q::rep>
struct poisson_distribution : public std::poisson_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::poisson_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::poisson_distribution<rep>;
poisson_distribution() : base() {}
explicit poisson_distribution(double p) : base(p) {}
@ -187,8 +187,8 @@ template<Quantity Q>
requires std::floating_point<typename Q::rep>
struct exponential_distribution : public std::exponential_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::exponential_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::exponential_distribution<rep>;
exponential_distribution() : base() {}
explicit exponential_distribution(const rep& lambda) : base(lambda) {}
@ -204,8 +204,8 @@ template<Quantity Q>
requires std::floating_point<typename Q::rep>
struct gamma_distribution : public std::gamma_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::gamma_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::gamma_distribution<rep>;
gamma_distribution() : base() {}
gamma_distribution(const rep& alpha, const rep& beta) : base(alpha, beta) {}
@ -221,8 +221,8 @@ template<Quantity Q>
requires std::floating_point<typename Q::rep>
struct weibull_distribution : public std::weibull_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::weibull_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::weibull_distribution<rep>;
weibull_distribution() : base() {}
weibull_distribution(const rep& a, const rep& b) : base(a, b) {}
@ -238,8 +238,8 @@ template<Quantity Q>
requires std::floating_point<typename Q::rep>
struct extreme_value_distribution : public std::extreme_value_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::extreme_value_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::extreme_value_distribution<rep>;
extreme_value_distribution() : base() {}
extreme_value_distribution(const Q& a, const rep& b) : base(a.count(), b) {}
@ -257,8 +257,8 @@ template<Quantity Q>
requires std::floating_point<typename Q::rep>
struct normal_distribution : public std::normal_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::normal_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::normal_distribution<rep>;
normal_distribution() : base() {}
normal_distribution(const Q& mean, const Q& stddev) : base(mean.count(), stddev.count()) {}
@ -277,8 +277,8 @@ template<Quantity Q>
requires std::floating_point<typename Q::rep>
struct lognormal_distribution : public std::lognormal_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::lognormal_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::lognormal_distribution<rep>;
lognormal_distribution() : base() {}
lognormal_distribution(const Q& m, const Q& s) : base(m.count(), s.count()) {}
@ -297,8 +297,8 @@ template<Quantity Q>
requires std::floating_point<typename Q::rep>
struct chi_squared_distribution : public std::chi_squared_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::chi_squared_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::chi_squared_distribution<rep>;
chi_squared_distribution() : base() {}
explicit chi_squared_distribution(const rep& n) : base(n) {}
@ -314,8 +314,8 @@ template<Quantity Q>
requires std::floating_point<typename Q::rep>
struct cauchy_distribution : public std::cauchy_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::cauchy_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::cauchy_distribution<rep>;
cauchy_distribution() : base() {}
cauchy_distribution(const Q& a, const Q& b) : base(a.count(), b.count()) {}
@ -334,8 +334,8 @@ template<Quantity Q>
requires std::floating_point<typename Q::rep>
struct fisher_f_distribution : public std::fisher_f_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::fisher_f_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::fisher_f_distribution<rep>;
fisher_f_distribution() : base() {}
fisher_f_distribution(const rep& m, const rep& n) : base(m, n) {}
@ -351,8 +351,8 @@ template<Quantity Q>
requires std::floating_point<typename Q::rep>
struct student_t_distribution : public std::student_t_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::student_t_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::student_t_distribution<rep>;
student_t_distribution() : base() {}
explicit student_t_distribution(const rep& n) : base(n) {}
@ -368,8 +368,8 @@ template<Quantity Q>
requires std::integral<typename Q::rep>
struct discrete_distribution : public std::discrete_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::discrete_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::discrete_distribution<rep>;
discrete_distribution() : base() {}
@ -393,8 +393,8 @@ template<Quantity Q>
requires std::floating_point<typename Q::rep>
class piecewise_constant_distribution : public std::piecewise_constant_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::piecewise_constant_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::piecewise_constant_distribution<rep>;
template <typename InputIt>
piecewise_constant_distribution(const std::vector<rep>& i, InputIt first_w) :
@ -438,8 +438,8 @@ template<Quantity Q>
requires std::floating_point<typename Q::rep>
class piecewise_linear_distribution : public std::piecewise_linear_distribution<typename Q::rep>
{
using rep = Q::rep;
using base = std::piecewise_linear_distribution<rep>;
using rep = TYPENAME Q::rep;
using base = TYPENAME std::piecewise_linear_distribution<rep>;
template <typename InputIt>
piecewise_linear_distribution(const std::vector<rep>& i, InputIt first_w) :

View File

@ -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;

View File

@ -26,7 +26,7 @@
#include <units/bits/external/hacks.h>
#include <gsl/gsl_assert>
#if COMP_GCC >= 10
#if COMP_MSVC || COMP_GCC >= 10
#include <compare>
#endif
@ -125,7 +125,7 @@ struct basic_symbol_text {
return basic_symbol_text<StandardCharT, 1, 1>(lhs) + rhs;
}
#if COMP_GCC >= 10
#if COMP_MSVC || COMP_GCC >= 10
template<typename StandardCharT2, std::size_t N2, std::size_t M2>
[[nodiscard]] friend constexpr auto operator<=>(const basic_symbol_text& lhs,

View File

@ -43,6 +43,6 @@ namespace units {
}
template<bool B, typename T, typename F>
using conditional = detail::conditional_impl<B>::template type<T, F>;
using conditional = TYPENAME detail::conditional_impl<B>::template type<T, F>;
}

View File

@ -37,5 +37,12 @@ target_link_libraries(unit_tests_runtime
$<IF:$<TARGET_EXISTS:CONAN_PKG::catch2>,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)

View File

@ -48,7 +48,7 @@ template<typename T>
struct typeinfo;
template<typename... Ts>
using dim_unpack = detail::dim_unpack<Ts...>::type;
using dim_unpack = TYPENAME detail::dim_unpack<Ts...>::type;
template<Exponent... Es>
using derived_dim = detail::derived_dimension_base<Es...>;

View File

@ -226,7 +226,7 @@ static_assert(quantity_point_cast<int>(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<dim_time, second, int>,
quantity_point<dim_length, metre, int>>); // different dimensions
#endif

View File

@ -142,7 +142,8 @@ static_assert(quantity_cast<fps::length<fps::foot>>(si::length<si::metre>(0.3048
// static_assert(1q_ft - si::length<si::metre>(1) == -si::length<si::metre>(0.6952)); // should not compile (different dimensions)
// static_assert(si::length<si::metre>(1) - 1q_ft == si::length<si::metre>(0.6952)); // should not compile (different dimensions)
static_assert(quantity_cast<si::length<si::metre>>(6.q_ft) - si::length<si::metre>(1) == si::length<si::metre>(0.8288)); // 6 ft in m - 1 m = ... m
static_assert(quantity_cast<si::length<si::metre>>(6.q_ft) - si::length<si::metre>(1) > si::length<si::metre>(0.8287) &&
quantity_cast<si::length<si::metre>>(6.q_ft) - si::length<si::metre>(1) < si::length<si::metre>(0.8289)); // 6 ft in m - 1 m = ... m
static_assert(si::length<si::metre>(5) - quantity_cast<si::length<si::metre>>(6q_ft) == si::length<si::metre>(3.1712)); // 5 m - 6 ft in m = ...
static_assert(6.q_ft - quantity_cast<fps::length<fps::foot>>(si::length<si::metre>(0.3048)) == 5.q_ft); // 6 ft - 1 ft in m = 5 ft
static_assert(quantity_cast<fps::length<fps::foot>>(si::length<si::metre>(1.8288)) - 1.q_ft == 5.q_ft); // 6 ft in m - 1 ft = 5 ft

View File

@ -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");