build: core library and each system separated to dedicated CMake targets
Refers to #249
This commit is contained in:
1 parent
7ee0e3ff90
commit
221883bb25
206 files changed
+547
-121
No files matched your search
+103
@@ -0,0 +1,103 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/bits/external/hacks.h>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef UNITS_DOWNCAST_MODE
|
||||
#if UNITS_DOWNCAST_MODE < 0 || UNITS_DOWNCAST_MODE > 2
|
||||
#error "Invalid UNITS_DOWNCAST_MODE value"
|
||||
#endif
|
||||
#else
|
||||
#define UNITS_DOWNCAST_MODE 1
|
||||
#endif
|
||||
|
||||
namespace units {
|
||||
|
||||
template<typename BaseType>
|
||||
struct downcast_base {
|
||||
using downcast_base_type = BaseType;
|
||||
friend auto downcast_guide(downcast_base);
|
||||
friend auto downcast_poison_pill(downcast_base);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
concept Downcastable =
|
||||
requires { typename T::downcast_base_type; } &&
|
||||
std::derived_from<T, downcast_base<typename T::downcast_base_type>>;
|
||||
|
||||
template<typename T>
|
||||
concept has_downcast_guide = requires(T t) { downcast_guide(t); };
|
||||
|
||||
template<typename T>
|
||||
concept has_downcast_poison_pill = requires(T t) { downcast_poison_pill(t); };
|
||||
|
||||
template<typename Target, Downcastable T>
|
||||
struct downcast_child : T {
|
||||
friend auto downcast_guide(typename T::downcast_base)
|
||||
{ return std::type_identity<Target>(); }
|
||||
};
|
||||
|
||||
template<Downcastable T>
|
||||
struct downcast_poison : T {
|
||||
friend auto downcast_poison_pill(typename T::downcast_base)
|
||||
{ return true; }
|
||||
};
|
||||
|
||||
enum class downcast_mode {
|
||||
off = 0, // no downcasting at all
|
||||
on = 1, // downcasting always forced -> compile-time errors in case of duplicated definitions
|
||||
automatic = 2 // downcasting automatically enabled if no collisions are present
|
||||
};
|
||||
|
||||
|
||||
template<typename Target, Downcastable T, downcast_mode mode = static_cast<downcast_mode>(UNITS_DOWNCAST_MODE)>
|
||||
struct downcast_dispatch : std::conditional_t<mode == downcast_mode::off, T,
|
||||
#ifdef UNITS_COMP_MSVC
|
||||
downcast_child<Target, T>> {};
|
||||
#else
|
||||
std::conditional_t<mode == downcast_mode::automatic && has_downcast_guide<T>,
|
||||
downcast_poison<T>, downcast_child<Target, T>>> {};
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
constexpr auto downcast_impl()
|
||||
{
|
||||
if constexpr(has_downcast_guide<downcast_base<T>> && !has_downcast_poison_pill<downcast_base<T>>)
|
||||
return decltype(downcast_guide(std::declval<downcast_base<T>>()))();
|
||||
else
|
||||
return std::type_identity<T>();
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<Downcastable T>
|
||||
using downcast = TYPENAME decltype(detail::downcast_impl<T>())::type;
|
||||
|
||||
template<Downcastable T>
|
||||
using downcast_base_t = TYPENAME T::downcast_base_type;
|
||||
|
||||
} // namespace units
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/bits/external/hacks.h>
|
||||
#include <cstdlib>
|
||||
#include <compare>
|
||||
|
||||
// TODO use <algorithm> when moved to C++20 modules (parsing takes too long for each translation unit)
|
||||
|
||||
namespace units {
|
||||
|
||||
/**
|
||||
* @brief A compile-time fixed string
|
||||
*
|
||||
* @tparam CharT Character type to be used by the string
|
||||
* @tparam N The size of the string
|
||||
*/
|
||||
template<typename CharT, std::size_t N>
|
||||
struct basic_fixed_string {
|
||||
CharT data_[N + 1] = {};
|
||||
|
||||
using iterator = CharT*;
|
||||
using const_iterator = const CharT*;
|
||||
|
||||
constexpr explicit(false) basic_fixed_string(CharT ch) noexcept { data_[0] = ch; }
|
||||
|
||||
constexpr explicit(false) basic_fixed_string(const CharT (&txt)[N + 1]) noexcept
|
||||
{
|
||||
if constexpr (N != 0)
|
||||
for (std::size_t i = 0; i < N; ++i) data_[i] = txt[i];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool empty() const noexcept { return N == 0; }
|
||||
[[nodiscard]] constexpr std::size_t size() const noexcept { return N; }
|
||||
[[nodiscard]] constexpr const CharT* data() const noexcept { return data_; }
|
||||
[[nodiscard]] constexpr const CharT* c_str() const noexcept { return data(); }
|
||||
[[nodiscard]] constexpr const CharT& operator[](std::size_t index) const noexcept { return data()[index]; }
|
||||
[[nodiscard]] constexpr CharT operator[](std::size_t index) noexcept { return data()[index]; }
|
||||
|
||||
[[nodiscard]] constexpr iterator begin() noexcept { return data(); }
|
||||
[[nodiscard]] constexpr const_iterator begin() const noexcept { return data(); }
|
||||
[[nodiscard]] constexpr iterator end() noexcept { return data() + size(); }
|
||||
[[nodiscard]] constexpr const_iterator end() const noexcept { return data() + size(); }
|
||||
|
||||
template<std::size_t N2>
|
||||
[[nodiscard]] constexpr friend basic_fixed_string<CharT, N + N2> operator+(
|
||||
const basic_fixed_string& lhs, const basic_fixed_string<CharT, N2>& rhs) noexcept
|
||||
{
|
||||
CharT txt[N + N2 + 1] = {};
|
||||
|
||||
for (size_t i = 0; i != N; ++i) txt[i] = lhs[i];
|
||||
for (size_t i = 0; i != N2; ++i) txt[N + i] = rhs[i];
|
||||
|
||||
return basic_fixed_string<CharT, N + N2>(txt);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool operator==(const basic_fixed_string& other) const
|
||||
{
|
||||
if (size() != other.size())
|
||||
return false;
|
||||
for (size_t i = 0; i != size(); ++i) {
|
||||
if ((*this)[i] != other[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
// return std::ranges::equal(*this, other);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
auto first1 = lhs.begin();
|
||||
const auto last1 = lhs.end();
|
||||
auto first2 = rhs.begin();
|
||||
const auto last2 = rhs.end();
|
||||
auto comp = std::compare_three_way();
|
||||
|
||||
for (; first1 != last1 && first2 != last2; ++first1, ++first2)
|
||||
if (auto cmp = comp(*first1, *first2); cmp != 0)
|
||||
return cmp;
|
||||
|
||||
return first1 != last1 ? std::strong_ordering::greater :
|
||||
first2 != last2 ? std::strong_ordering::less :
|
||||
std::strong_ordering::equal;
|
||||
// return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename CharT, std::size_t N>
|
||||
basic_fixed_string(const CharT (&str)[N]) -> basic_fixed_string<CharT, N - 1>;
|
||||
|
||||
template<typename CharT>
|
||||
basic_fixed_string(CharT) -> basic_fixed_string<CharT, 1>;
|
||||
|
||||
template<std::size_t N>
|
||||
using fixed_string = basic_fixed_string<char, N>;
|
||||
|
||||
} // namespace units
|
||||
@@ -0,0 +1,36 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/bits/external/fixed_string.h>
|
||||
#include <ostream>
|
||||
|
||||
namespace units {
|
||||
|
||||
template<typename CharT, class Traits, std::size_t N>
|
||||
std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const basic_fixed_string<CharT, N>& txt)
|
||||
{
|
||||
return os << txt.c_str();
|
||||
}
|
||||
|
||||
} // namespace units
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if __clang__
|
||||
#define UNITS_COMP_CLANG __clang_major__
|
||||
#elif __GNUC__
|
||||
#define UNITS_COMP_GCC __GNUC__
|
||||
#define UNITS_COMP_GCC_MINOR __GNUC_MINOR__
|
||||
#elif _MSC_VER
|
||||
#define UNITS_COMP_MSVC _MSC_VER
|
||||
#endif
|
||||
|
||||
#if UNITS_COMP_CLANG
|
||||
|
||||
#include <ciso646>
|
||||
#if _LIBCPP_VERSION
|
||||
#define UNITS_LIBCXX _LIBCPP_VERSION
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if UNITS_COMP_CLANG == 12 && UNITS_LIBCXX
|
||||
|
||||
#include <concepts/compare.hpp>
|
||||
#include <concepts/concepts.hpp>
|
||||
#include <range/v3/functional/comparisons.hpp>
|
||||
#include <range/v3/iterator.hpp>
|
||||
#include <range/v3/range/concepts.hpp>
|
||||
#include <range/v3/algorithm/lower_bound.hpp>
|
||||
#include <range/v3/algorithm/transform.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
#include <concepts>
|
||||
#include <compare>
|
||||
|
||||
#if UNITS_COMP_MSVC || UNITS_COMP_CLANG
|
||||
|
||||
#define TYPENAME typename
|
||||
|
||||
#else
|
||||
|
||||
#define TYPENAME
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
namespace std {
|
||||
|
||||
#if UNITS_COMP_GCC
|
||||
|
||||
template<class T>
|
||||
concept default_constructible = constructible_from<T>;
|
||||
|
||||
#elif UNITS_COMP_CLANG && UNITS_LIBCXX
|
||||
|
||||
// concepts
|
||||
using concepts::common_with;
|
||||
using concepts::constructible_from;
|
||||
using concepts::convertible_to;
|
||||
using concepts::copy_constructible;
|
||||
using concepts::derived_from;
|
||||
using concepts::equality_comparable;
|
||||
using concepts::equality_comparable_with;
|
||||
using concepts::integral;
|
||||
using concepts::move_constructible;
|
||||
using concepts::regular;
|
||||
using concepts::three_way_comparable;
|
||||
using concepts::three_way_comparable_with;
|
||||
using concepts::totally_ordered;
|
||||
|
||||
using ranges::compare_three_way;
|
||||
|
||||
namespace ranges {
|
||||
|
||||
using ::ranges::begin;
|
||||
using ::ranges::end;
|
||||
using ::ranges::distance;
|
||||
|
||||
using ::ranges::forward_range;
|
||||
using ::ranges::input_range;
|
||||
using ::ranges::range_value_t;
|
||||
|
||||
using ::ranges::lower_bound;
|
||||
using ::ranges::transform;
|
||||
|
||||
}
|
||||
|
||||
// missing in Range-v3
|
||||
template<class T>
|
||||
concept floating_point = std::is_floating_point_v<T>;
|
||||
|
||||
template<class T>
|
||||
concept default_initializable =
|
||||
std::constructible_from<T> &&
|
||||
requires { T{}; } &&
|
||||
requires { ::new (static_cast<void*>(nullptr)) T; };
|
||||
|
||||
template<class F, class... Args>
|
||||
concept invocable =
|
||||
requires(F&& f, Args&&... args) {
|
||||
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
|
||||
};
|
||||
|
||||
template<class F, class... Args>
|
||||
concept regular_invocable = invocable<F, Args...>;
|
||||
|
||||
template<class T, class U>
|
||||
constexpr bool cmp_equal(T t, U u) noexcept
|
||||
{
|
||||
using UT = std::make_unsigned_t<T>;
|
||||
using UU = std::make_unsigned_t<U>;
|
||||
if constexpr (std::is_signed_v<T> == std::is_signed_v<U>)
|
||||
return t == u;
|
||||
else if constexpr (std::is_signed_v<T>)
|
||||
return t < 0 ? false : UT(t) == u;
|
||||
else
|
||||
return u < 0 ? false : t == UU(u);
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
constexpr bool cmp_not_equal(T t, U u) noexcept
|
||||
{
|
||||
return !cmp_equal(t, u);
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
constexpr bool cmp_less(T t, U u) noexcept
|
||||
{
|
||||
using UT = std::make_unsigned_t<T>;
|
||||
using UU = std::make_unsigned_t<U>;
|
||||
if constexpr (std::is_signed_v<T> == std::is_signed_v<U>)
|
||||
return t < u;
|
||||
else if constexpr (std::is_signed_v<T>)
|
||||
return t < 0 ? true : UT(t) < u;
|
||||
else
|
||||
return u < 0 ? false : t < UU(u);
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
constexpr bool cmp_greater(T t, U u) noexcept
|
||||
{
|
||||
return cmp_less(u, t);
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
constexpr bool cmp_less_equal(T t, U u) noexcept
|
||||
{
|
||||
return !cmp_greater(t, u);
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
constexpr bool cmp_greater_equal(T t, U u) noexcept
|
||||
{
|
||||
return !cmp_less(t, u);
|
||||
}
|
||||
|
||||
template<class R, class T>
|
||||
constexpr bool in_range(T t) noexcept
|
||||
{
|
||||
return std::cmp_greater_equal(t, std::numeric_limits<R>::min()) &&
|
||||
std::cmp_less_equal(t, std::numeric_limits<R>::max());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace std
|
||||
@@ -0,0 +1,77 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/bits/external/fixed_string.h>
|
||||
#include <units/symbol_text.h>
|
||||
|
||||
namespace units::detail {
|
||||
|
||||
template<std::intmax_t Value>
|
||||
requires (0 <= Value) && (Value < 10)
|
||||
inline constexpr basic_fixed_string superscript_number = "";
|
||||
|
||||
template<> inline constexpr basic_fixed_string superscript_number<0> = "\u2070";
|
||||
template<> inline constexpr basic_fixed_string superscript_number<1> = "\u00b9";
|
||||
template<> inline constexpr basic_fixed_string superscript_number<2> = "\u00b2";
|
||||
template<> inline constexpr basic_fixed_string superscript_number<3> = "\u00b3";
|
||||
template<> inline constexpr basic_fixed_string superscript_number<4> = "\u2074";
|
||||
template<> inline constexpr basic_fixed_string superscript_number<5> = "\u2075";
|
||||
template<> inline constexpr basic_fixed_string superscript_number<6> = "\u2076";
|
||||
template<> inline constexpr basic_fixed_string superscript_number<7> = "\u2077";
|
||||
template<> inline constexpr basic_fixed_string superscript_number<8> = "\u2078";
|
||||
template<> inline constexpr basic_fixed_string superscript_number<9> = "\u2079";
|
||||
|
||||
inline constexpr basic_symbol_text superscript_minus("\u207b", "-");
|
||||
|
||||
inline constexpr basic_symbol_text superscript_prefix("", "^");
|
||||
|
||||
template<std::intmax_t Value>
|
||||
constexpr auto superscript_helper()
|
||||
{
|
||||
if constexpr(Value < 0)
|
||||
return superscript_minus + superscript_helper<-Value>();
|
||||
else if constexpr(Value < 10)
|
||||
return basic_symbol_text(superscript_number<Value>, basic_fixed_string(static_cast<char>('0' + Value)));
|
||||
else
|
||||
return superscript_helper<Value / 10>() + superscript_helper<Value % 10>();
|
||||
}
|
||||
|
||||
template<std::intmax_t Value>
|
||||
constexpr auto superscript()
|
||||
{
|
||||
return superscript_prefix + superscript_helper<Value>();
|
||||
}
|
||||
|
||||
template<std::intmax_t Value>
|
||||
constexpr auto regular()
|
||||
{
|
||||
if constexpr (Value < 0)
|
||||
return basic_fixed_string("-") + superscript_helper<-Value>();
|
||||
else if constexpr (Value < 10)
|
||||
return basic_symbol_text(static_cast<char>('0' + Value));
|
||||
else
|
||||
return regular<Value / 10>() + regular<Value % 10>();
|
||||
}
|
||||
|
||||
} // namespace units::detail
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <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 {
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool is_type_list = false;
|
||||
|
||||
template<template<typename...> typename T, typename... Types>
|
||||
inline constexpr bool is_type_list<T<Types...>> = true;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename T>
|
||||
concept TypeList = detail::is_type_list<T>;
|
||||
|
||||
// push_front
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename List, typename... Types>
|
||||
struct type_list_push_front_impl;
|
||||
|
||||
template<template<typename...> typename List, typename... OldTypes, typename... NewTypes>
|
||||
struct type_list_push_front_impl<List<OldTypes...>, NewTypes...> {
|
||||
using type = List<NewTypes..., OldTypes...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<TypeList List, typename... Types>
|
||||
using type_list_push_front = TYPENAME detail::type_list_push_front_impl<List, Types...>::type;
|
||||
|
||||
// push_back
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename List, typename... Types>
|
||||
struct type_list_push_back_impl;
|
||||
|
||||
template<template<typename...> typename List, typename... OldTypes, typename... NewTypes>
|
||||
struct type_list_push_back_impl<List<OldTypes...>, NewTypes...> {
|
||||
using type = List<OldTypes..., NewTypes...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<TypeList List, typename... Types>
|
||||
using type_list_push_back = TYPENAME detail::type_list_push_back_impl<List, Types...>::type;
|
||||
|
||||
// join
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename List, typename... Rest>
|
||||
struct type_list_join_impl {
|
||||
using type = List;
|
||||
};
|
||||
|
||||
template<template<typename...> typename List, typename... First, typename... Second, typename... Rest>
|
||||
struct type_list_join_impl<List<First...>, List<Second...>, Rest...> {
|
||||
using type = TYPENAME type_list_join_impl<List<First..., Second...>, Rest...>::type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<TypeList... Lists>
|
||||
using type_list_join = TYPENAME detail::type_list_join_impl<Lists...>::type;
|
||||
|
||||
// split
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<template<typename...> typename List, std::size_t Idx, std::size_t N, typename... Types>
|
||||
struct split_impl;
|
||||
|
||||
template<template<typename...> typename List, std::size_t Idx, std::size_t N>
|
||||
struct split_impl<List, Idx, N> {
|
||||
using first_list = List<>;
|
||||
using second_list = List<>;
|
||||
};
|
||||
|
||||
template<template<typename...> typename List, std::size_t Idx, std::size_t N, typename T, typename... Rest>
|
||||
requires (Idx < N)
|
||||
struct split_impl<List, Idx, N, T, Rest...> : split_impl<List, Idx + 1, N, Rest...> {
|
||||
using base = split_impl<List, Idx + 1, N, Rest...>;
|
||||
using first_list = TYPENAME type_list_push_front_impl<typename base::first_list, T>::type;
|
||||
using second_list = TYPENAME base::second_list;
|
||||
};
|
||||
|
||||
template<template<typename...> typename List, std::size_t Idx, std::size_t N, typename T, typename... Rest>
|
||||
struct split_impl<List, Idx, N, T, Rest...> : split_impl<List, Idx + 1, N, Rest...> {
|
||||
using base = split_impl<List, Idx + 1, N, Rest...>;
|
||||
using first_list = TYPENAME base::first_list;
|
||||
using second_list = TYPENAME type_list_push_front_impl<typename base::second_list, T>::type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<TypeList List, std::size_t N>
|
||||
struct type_list_split;
|
||||
|
||||
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 = TYPENAME split::first_list;
|
||||
using second_list = TYPENAME split::second_list;
|
||||
};
|
||||
|
||||
// split_half
|
||||
|
||||
template<TypeList List>
|
||||
struct type_list_split_half;
|
||||
|
||||
template<template<typename...> typename List, typename... Types>
|
||||
struct type_list_split_half<List<Types...>> : type_list_split<List<Types...>, (sizeof...(Types) + 1) / 2> {
|
||||
};
|
||||
|
||||
// merge_sorted
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename SortedList1, typename SortedList2, template<typename, typename> typename Pred>
|
||||
struct type_list_merge_sorted_impl;
|
||||
|
||||
template<template<typename...> typename List, template<typename, typename> typename Pred>
|
||||
struct type_list_merge_sorted_impl<List<>, List<>, Pred> {
|
||||
using type = List<>;
|
||||
};
|
||||
|
||||
template<template<typename...> typename List, typename... Lhs, template<typename, typename> typename Pred>
|
||||
struct type_list_merge_sorted_impl<List<Lhs...>, List<>, Pred> {
|
||||
using type = List<Lhs...>;
|
||||
};
|
||||
|
||||
template<template<typename...> typename List, typename... Rhs, template<typename, typename> typename Pred>
|
||||
struct type_list_merge_sorted_impl<List<>, List<Rhs...>, Pred> {
|
||||
using type = List<Rhs...>;
|
||||
};
|
||||
|
||||
|
||||
template<template<typename...> typename List, typename Lhs1, typename... LhsRest, typename Rhs1, typename... RhsRest,
|
||||
template<typename, typename> typename Pred>
|
||||
requires Pred<Lhs1, Rhs1>::value
|
||||
struct type_list_merge_sorted_impl<List<Lhs1, LhsRest...>, List<Rhs1, RhsRest...>, Pred> {
|
||||
using type = TYPENAME type_list_push_front_impl<typename type_list_merge_sorted_impl<List<LhsRest...>, List<Rhs1, RhsRest...>, Pred>::type, Lhs1>::type;
|
||||
};
|
||||
|
||||
template<template<typename...> typename List, typename Lhs1, typename... LhsRest, typename Rhs1, typename... RhsRest,
|
||||
template<typename, typename> typename Pred>
|
||||
struct type_list_merge_sorted_impl<List<Lhs1, LhsRest...>, List<Rhs1, RhsRest...>, Pred> {
|
||||
using type = TYPENAME type_list_push_front_impl<typename type_list_merge_sorted_impl<List<Lhs1, LhsRest...>, List<RhsRest...>, Pred>::type, Rhs1>::type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<TypeList SortedList1, TypeList SortedList2, template<typename, typename> typename Pred>
|
||||
using type_list_merge_sorted = TYPENAME detail::type_list_merge_sorted_impl<SortedList1, SortedList2, Pred>::type;
|
||||
|
||||
// sort
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename List, template<typename, typename> typename Pred>
|
||||
struct type_list_sort_impl;
|
||||
|
||||
template<template<typename...> typename List, template<typename, typename> typename Pred>
|
||||
struct type_list_sort_impl<List<>, Pred> {
|
||||
using type = List<>;
|
||||
};
|
||||
|
||||
template<template<typename...> typename List, typename T, template<typename, typename> typename Pred>
|
||||
struct type_list_sort_impl<List<T>, Pred> {
|
||||
using type = List<T>;
|
||||
};
|
||||
|
||||
template<template<typename...> typename List, typename... Types, template<typename, typename> typename Pred>
|
||||
struct type_list_sort_impl<List<Types...>, Pred> {
|
||||
using types = List<Types...>;
|
||||
using split = type_list_split_half<List<Types...>>;
|
||||
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 = TYPENAME detail::type_list_sort_impl<List, Pred>::type;
|
||||
|
||||
} // namespace units
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif //_MSC_VER
|
||||
@@ -0,0 +1,80 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/bits/external/hacks.h>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace units {
|
||||
|
||||
// conditional
|
||||
namespace detail {
|
||||
|
||||
template<bool>
|
||||
struct conditional_impl {
|
||||
template<typename T, typename F>
|
||||
using type = F;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct conditional_impl<true> {
|
||||
template<typename T, typename F>
|
||||
using type = T;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<bool B, typename T, typename F>
|
||||
using conditional = TYPENAME detail::conditional_impl<B>::template type<T, F>;
|
||||
|
||||
// is_same
|
||||
template<class T, class U>
|
||||
inline constexpr bool is_same_v = false;
|
||||
|
||||
template<class T>
|
||||
inline constexpr bool is_same_v<T, T> = true;
|
||||
|
||||
template<class T, class U>
|
||||
using is_same = std::bool_constant<is_same_v<T, U>>;
|
||||
|
||||
// is_specialization_of
|
||||
template<typename T, template<typename...> typename Type>
|
||||
inline constexpr bool is_specialization_of = false;
|
||||
|
||||
template<typename... Params, template<typename...> typename Type>
|
||||
inline constexpr bool is_specialization_of<Type<Params...>, Type> = true;
|
||||
|
||||
// is_derived_from_specialization_of
|
||||
namespace detail {
|
||||
|
||||
template<template<typename...> typename Type, typename... Params>
|
||||
void to_base_specialization_of(const volatile Type<Params...>*);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename T, template<typename...> typename Type>
|
||||
// inline constexpr bool // TODO: Replace with concept when it works with MSVC
|
||||
concept is_derived_from_specialization_of = requires(T* t) { detail::to_base_specialization_of<Type>(t); };
|
||||
|
||||
} // namespace units
|
||||
Reference in new issue
Block a user