build: core library and each system separated to dedicated CMake targets

Refers to #249
This commit is contained in:
Mateusz Pusz committed 2021-03-16 23:05:45 +01:00
1 parent 7ee0e3ff90
commit 221883bb25
206 files changed
+547 -121

No files matched your search

+103
View File
@@ -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
View File
@@ -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
+36
View File
@@ -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
View File
@@ -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
+77
View File
@@ -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
View File
@@ -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
+80
View File
@@ -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