mirror of
https://github.com/mpusz/mp-units.git
synced 2025-06-25 01:01:33 +02:00
VS2019 support added
This commit is contained in:
Submodule cmake/common updated: eb5fbd40d1...ba5b1163c1
12
conanfile.py
12
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):
|
||||
|
@ -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;
|
||||
|
||||
// ...
|
||||
};
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
24
src/include/units/bits/external/fixed_string.h
vendored
24
src/include/units/bits/external/fixed_string.h
vendored
@ -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
|
||||
|
18
src/include/units/bits/external/hacks.h
vendored
18
src/include/units/bits/external/hacks.h
vendored
@ -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
|
||||
|
31
src/include/units/bits/external/type_list.h
vendored
31
src/include/units/bits/external/type_list.h
vendored
@ -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
|
||||
|
@ -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>
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <units/bits/external/hacks.h>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
|
@ -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()));
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 {};
|
||||
|
@ -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;
|
||||
|
@ -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())));
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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> {};
|
||||
|
||||
|
@ -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)> {};
|
||||
|
@ -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> {};
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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) :
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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>;
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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...>;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
||||
|
Reference in New Issue
Block a user