Text formatting enabled + directory tree refactoring

This commit is contained in:
Mateusz Pusz
2019-12-11 08:07:13 +01:00
parent 8ffc46ba75
commit bc1901f4f0
30 changed files with 507 additions and 236 deletions
+72
View File
@@ -0,0 +1,72 @@
// 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>
namespace units {
template<typename BaseType>
struct downcast_base {
using downcast_base_type = BaseType;
friend auto downcast_guide(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 Target, Downcastable T>
struct downcast_child : T {
friend auto downcast_guide(typename downcast_child::downcast_base) { return Target(); }
};
namespace detail {
template<typename T>
concept has_downcast = requires {
downcast_guide(std::declval<downcast_base<T>>());
};
template<typename T>
constexpr auto downcast_impl()
{
if constexpr(has_downcast<T>)
return decltype(downcast_guide(std::declval<downcast_base<T>>()))();
else
return T();
}
}
template<Downcastable T>
using downcast = decltype(detail::downcast_impl<T>());
template<Downcastable T>
using downcast_base_t = T::downcast_base_type;
} // namespace units
+111
View File
@@ -0,0 +1,111 @@
// 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 <cstdlib>
#include <ostream>
namespace units {
template<typename CharT, std::size_t N>
struct basic_fixed_string {
CharT data_[N + 1] = {};
constexpr basic_fixed_string(CharT ch) noexcept
{
data_[0] = ch;
}
constexpr basic_fixed_string(const CharT (&txt)[N + 1]) noexcept
{
for(std::size_t i = 0; i < N; ++i)
data_[i] = txt[i];
}
[[nodiscard]] constexpr std::size_t size() const noexcept { return N; }
[[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]; }
// auto operator==(const basic_fixed_string &) = default;
[[nodiscard]] constexpr friend bool operator==(const basic_fixed_string& lhs, const basic_fixed_string& rhs) noexcept
{
for(size_t i = 0; i != lhs.size(); ++i)
if(lhs.data_[i] != rhs.data_[i])
return false;
return true;
}
template<typename CharT2, std::size_t N2>
[[nodiscard]] constexpr friend bool operator==(const basic_fixed_string&, const basic_fixed_string<CharT2, N2>&) noexcept
{
return false;
}
template<typename CharT2, std::size_t N2>
[[nodiscard]] constexpr friend bool operator<(const basic_fixed_string& lhs, const basic_fixed_string<CharT2, N2>& rhs) noexcept
{
using std::begin, std::end;
auto first1 = begin(lhs.data_);
auto first2 = begin(rhs.data_);
const auto last1 = std::prev(end(lhs.data_)); // do not waste time for '\0'
const auto last2 = std::prev(end(rhs.data_));
for(; (first1 != last1) && (first2 != last2); ++first1, (void)++first2 ) {
if(*first1 < *first2) return true;
if(*first2 < *first1) return false;
}
return first1 == last1 && first2 != last2;
}
template<class Traits>
friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const basic_fixed_string& txt)
{
return os << txt.c_str();
}
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 units::basic_fixed_string(txt);
}
};
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>;
}
+81
View File
@@ -0,0 +1,81 @@
// 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 <functional>
#ifdef NDEBUG
#define Expects(cond) (void)(cond);
#else
#include <cassert>
#define Expects(cond) assert(cond);
#endif
#if __GNUC__ < 10
#include <concepts/concepts.hpp>
#define AUTO
#define SAME_AS(T) T
#else
#include <concepts>
#define AUTO auto
#define SAME_AS(T) std::same_as<T>
#endif
namespace std {
#if __GNUC__ < 10
// concepts
using concepts::common_reference_with;
using concepts::common_with;
using concepts::constructible_from;
using concepts::convertible_to;
using concepts::default_constructible;
using concepts::derived_from;
using concepts::equality_comparable_with;
using concepts::regular;
using concepts::same_as;
using concepts::totally_ordered;
using concepts::totally_ordered_with;
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...>;
#else
template<class T>
concept default_constructible = constructible_from<T>;
#endif
} // namespace std
+399
View File
@@ -0,0 +1,399 @@
// 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>
// P1813 - A Concept Design for the Numeric Algorithms
namespace std {
template<class BOp, class T, class U = T>
struct left_identity {};
template<class BOp, class T, class U = T>
using left_identity_t = decltype(declval<left_identity<BOp, T, U>>()());
template<class BOp, class T, class U = T>
struct right_identity {};
template<class BOp, class T, class U = T>
using right_identity_t = decltype(declval<right_identity<BOp, T, U>>()());
namespace detail {
template<class BOp, class T, class U>
concept has_two_sided_identity = // exposition only
requires(BOp bop, const T& t, const U& u) {
typename left_identity_t<BOp, T, U>;
typename left_identity_t<BOp, U, T>;
typename right_identity_t<BOp, T, U>;
typename right_identity_t<BOp, U, T>;
requires same_as<left_identity_t<BOp, T, U>, left_identity_t<BOp, U, T>>;
requires same_as<right_identity_t<BOp, T, U>, right_identity_t<BOp, U, T>>;
requires same_as<left_identity_t<BOp, T, U>, right_identity_t<BOp, T, U>>;
};
}
template<class BOp, class T, class U = T>
requires detail::has_two_sided_identity<BOp, T, U>
struct two_sided_identity {
constexpr common_type_t<T, U> operator()() const;
};
template<class BOp, class T, class U>
using two_sided_identity_t = decltype(two_sided_identity<BOp&, T, U>());
template<class BOp, class T, class U = T>
struct left_zero {};
template<class BOp, class T, class U = T>
using left_zero_t = decltype(declval<left_zero<BOp, T, U>>()());
template<class BOp, class T, class U = T>
struct right_zero {};
template<class BOp, class T, class U = T>
using right_zero_t = decltype(declval<right_zero<BOp, T, U>>()());
namespace detail {
template<class BOp, class T, class U>
concept has_two_sided_zero = // exposition only
requires(BOp bop, const T& t, const U& u) {
typename left_zero_t<BOp, T, U>;
typename left_zero_t<BOp, U, T>;
typename right_zero_t<BOp, T, U>;
typename right_zero_t<BOp, U, T>;
requires same_as<left_zero_t<BOp, T, U>, left_zero_t<BOp, U, T>>;
requires same_as<right_zero_t<BOp, T, U>, right_zero_t<BOp, U, T>>;
requires same_as<left_zero_t<BOp, T, U>, right_zero_t<BOp, T, U>>;
};
}
template<class BOp, class T, class U>
requires detail::has_two_sided_zero<BOp, T, U>
struct two_sided_zero {
constexpr common_type_t<T, U> operator()(BOp bop, T&& t, U&& u) const;
};
template<class BOp, class T, class U = T>
using two_sided_zero_t = decltype(two_sided_zero<BOp&, T, U>());
template<class BOp>
struct inverse_traits {};
template<class BOp>
using inverse_operation_t = typename inverse_traits<BOp>::type;
template<class BOp, class T, class U>
concept commutative_operation =
regular_invocable<BOp, T, U> &&
regular_invocable<BOp, U, T> &&
common_with<T, U> &&
equality_comparable_with<T, U>;
template<class BOp, class T, class U>
concept magma =
common_with<T, U> &&
regular_invocable<BOp, T, T> &&
regular_invocable<BOp, U, U> &&
regular_invocable<BOp, T, U> &&
regular_invocable<BOp, U, T> &&
common_with<invoke_result_t<BOp&, T, U>, T> &&
common_with<invoke_result_t<BOp&, T, U>, U> &&
same_as<invoke_result_t<BOp&, T, U>, invoke_result_t<BOp&, U, T>>;
template<class BOp, class T, class U>
concept semigroup = magma<BOp, T, U>;
template<class BOp, class T, class U = T>
concept monoid = semigroup<BOp, T, U> &&
requires {
typename two_sided_identity_t<BOp, remove_cvref_t<T>, remove_cvref_t<U>>;
};
template<class BOp, class T, class U>
concept quasigroup = magma<BOp, T, U> &&
requires {
typename inverse_operation_t<BOp>;
typename inverse_operation_t<inverse_operation_t<BOp>>;
requires same_as<BOp, inverse_operation_t<inverse_operation_t<BOp>>>;
};
template<class BOp, class T, class U>
concept loop = quasigroup<BOp, T, U> &&
requires {
typename two_sided_identity_t<BOp, remove_cvref_t<T>, remove_cvref_t<U>>;
};
template<class BOp, class T, class U>
concept group = semigroup<BOp, T, U> && quasigroup<BOp, T, U>;
template<class BOp, class T, class U>
concept abelian_group = group<BOp, T, U> && commutative_operation<BOp, T, U>;
template<class BOp1, class BOp2, class T, class U, class V>
concept weak_magmaring = magma<BOp2, U, V> && magma<BOp1, T, invoke_result_t<BOp2&, U, V>>;
template<class BOp1, class BOp2, class T, class U, class V>
concept near_semiring = weak_magmaring<BOp1, BOp2, T, U, V> &&
monoid<BOp1, T, invoke_result_t<BOp2&, U, V>> && semigroup<BOp2, U, V> &&
requires {
typename two_sided_zero_t<BOp2, remove_cvref_t<U>, remove_cvref_t<V>>;
};
namespace ranges {
namespace detail {
template<class T, class U>
concept summable_with = // exposition only
default_constructible<remove_reference_t<T>> &&
default_constructible<remove_reference_t<U>> &&
common_reference_with<T, U> &&
requires(T&& t, U&& u) {
{ std::forward<T>(t) + std::forward<T>(t) } -> common_with<T>;
{ std::forward<U>(u) + std::forward<U>(u) } -> common_with<U>;
{ std::forward<T>(t) + std::forward<U>(u) } -> common_with<T>;
{ std::forward<U>(u) + std::forward<T>(t) } -> common_with<U>;
requires same_as<decltype(std::forward<T>(t) + std::forward<U>(u)),
decltype(std::forward<U>(u) + std::forward<T>(t))>;
};
}
struct plus {
template<class T, detail::summable_with<T> U>
constexpr decltype(auto) operator()(T&& t, U&& u) const {
return std::forward<T>(t) + std::forward<U>(u);
}
using is_transparent = std::true_type;
};
namespace detail {
template<class T>
concept negatable = // exposition only
summable_with<T, T> &&
totally_ordered<T> &&
requires(T&& t) {
{ -std::forward<T>(t) } -> common_with<T>;
};
}
struct negate {
template<detail::negatable T>
constexpr decltype(auto) operator()(T&& t) const {
return -std::forward<T>(t);
}
using is_transparent = std::true_type;
};
namespace detail {
template<class T, class U>
concept differenceable_with = // exposition only
summable_with<T, U> &&
negatable<T> &&
negatable<U> &&
totally_ordered_with<T, U> &&
requires(T&& t, U&& u) {
{ std::forward<T>(t) - std::forward<T>(t) } -> common_with<T>;
{ std::forward<U>(u) - std::forward<U>(u) } -> common_with<U>;
{ std::forward<T>(t) - std::forward<U>(u) } -> common_with<T>;
{ std::forward<U>(u) - std::forward<T>(t) } -> common_with<U>;
requires same_as<decltype(std::forward<T>(t) - std::forward<U>(u)),
decltype(std::forward<U>(u) - std::forward<T>(t))>;
};
}
struct minus {
template<class T, detail::differenceable_with<T> U>
constexpr decltype(auto) operator()(T&& t, U&& u) const {
return std::forward<T>(t) - std::forward<U>(u);
}
using is_transparent = std::true_type;
};
namespace detail {
template<class T, class U>
concept multiplicable_with = // exposition only
detail::summable_with<T, U> &&
constructible_from<remove_cvref_t<T>, int> && // specifically T{0} and T{1}
constructible_from<remove_cvref_t<U>, int> && // specifically U{0} and U{1}
constructible_from<remove_cvref_t<common_type_t<T, U>>, int> &&
common_reference_with<T, U> &&
requires(T&& t, U&& u) {
{ std::forward<T>(t) * std::forward<T>(t) } -> common_with<T>;
{ std::forward<U>(u) * std::forward<U>(u) } -> common_with<U>;
{ std::forward<T>(t) * std::forward<U>(u) } -> common_with<T>;
{ std::forward<U>(u) * std::forward<T>(t) } -> common_with<U>;
requires same_as<decltype(std::forward<T>(t) * std::forward<U>(u)),
decltype(std::forward<U>(u) * std::forward<T>(t))>;
};
}
struct times {
template<class T, detail::multiplicable_with<T> U>
constexpr decltype(auto) operator()(T&& t, U&& u) const
{ return std::forward<T>(t) * std::forward<U>(u); }
using is_transparent = std::true_type;
};
namespace detail {
template<class T, class U>
concept divisible_with = // exposition only
multiplicable_with<T, U> &&
differenceable_with<T, U> &&
requires(T&& t, U&& u) {
{ std::forward<T>(t) / std::forward<T>(t) } -> common_with<T>;
{ std::forward<U>(u) / std::forward<U>(u) } -> common_with<U>;
{ std::forward<T>(t) / std::forward<U>(u) } -> common_with<T>;
{ std::forward<U>(u) / std::forward<T>(t) } -> common_with<U>;
requires same_as<decltype(std::forward<T>(t) / std::forward<U>(u)),
decltype(std::forward<U>(u) / std::forward<T>(t))>;
};
}
struct divided_by {
template<class T, detail::divisible_with<T> U>
constexpr decltype(auto) operator()(T&& t, U&& u) const
{ return std::forward<T>(t) / std::forward<U>(u); }
};
namespace detail {
template<class T, class Q>
concept modulo_with = // exposition only
divisible_with<T, Q> &&
requires(T&& t, Q&& q) {
{ std::forward<T>(t) % std::forward<T>(t) } -> common_with<T>;
{ std::forward<Q>(q) % std::forward<Q>(q) } -> common_with<Q>;
{ std::forward<T>(t) % std::forward<Q>(q) } -> common_with<T>;
{ std::forward<Q>(q) % std::forward<T>(t) } -> common_with<Q>;
requires same_as<decltype(std::forward<T>(t) % std::forward<Q>(q)),
decltype(std::forward<Q>(q) % std::forward<T>(t))>;
};
}
struct modulus {
template<class T, detail::modulo_with<T> U>
constexpr decltype(auto) operator()(T&& t, U&& u) const
{ return std::forward<T>(t) % std::forward<U>(u); }
};
} // namespace ranges
template<class T, class U>
requires magma<ranges::plus, T, U>
struct left_identity<ranges::plus, T, U> {
constexpr common_type_t<T, U> operator()() const { return T{}; }
};
template<class T, class U>
requires magma<ranges::plus, T, U>
struct right_identity<ranges::plus, T, U> {
constexpr common_type_t<T, U> operator()() const { return U{}; }
};
template<>
struct inverse_traits<ranges::plus> {
using type = ranges::minus;
constexpr type operator()() const noexcept { return type{}; }
};
template<class T, class U>
struct right_identity<ranges::minus, T, U> : private right_identity<ranges::plus, T, U> {
using right_identity<ranges::plus, T, U>::operator();
};
template<>
struct inverse_traits<ranges::minus> {
using type = ranges::plus;
constexpr type operator()() const noexcept { return type{}; }
};
template<class T, class U>
requires magma<ranges::times, T, U>
struct left_identity<ranges::times, T, U> {
constexpr common_type_t<T, U> operator()() const { return T{1}; }
};
template<class T, class U>
requires magma<ranges::times, T, U>
struct right_identity<ranges::times, T, U> {
constexpr common_type_t<T, U> operator()() const { return U{1}; }
};
template<class T, class U>
requires magma<ranges::times, T, U>
struct left_zero<ranges::times, T, U> {
constexpr common_type_t<T, U> operator()() const { return T{}; }
};
template<class T, class U>
requires magma<ranges::times, T, U>
struct right_zero<ranges::times, T, U> {
constexpr common_type_t<T, U> operator()() const { return U{}; }
};
template<>
struct inverse_traits<ranges::times> {
using type = ranges::divided_by;
constexpr type operator()() const noexcept { return type{}; }
};
template<class T, class U>
requires magma<ranges::divided_by, T, U>
struct right_identity<ranges::divided_by, T, U> {
constexpr common_type_t<T, U> operator()() const { return U{1}; }
};
template<>
struct inverse_traits<ranges::divided_by> {
using type = ranges::times;
constexpr type operator()() const noexcept { return type{}; }
};
template<class T, class U>
requires magma<ranges::modulus, T, U>
struct left_zero<ranges::modulus, T, U> {
constexpr common_type_t<T, U> operator()() const { return T{}; }
};
} // namespace std
+64
View File
@@ -0,0 +1,64 @@
// 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>
namespace units::detail {
template<int 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";
template<int Value>
requires (Value >= 0)
constexpr auto superscript()
{
if constexpr(Value < 10)
return superscript_number<Value>;
else
return superscript<Value / 10>() + superscript<Value % 10>();
}
template<int Value>
requires (Value >= 0)
constexpr auto regular()
{
if constexpr(Value < 10)
return basic_fixed_string(static_cast<char>('0' + Value));
else
return regular<Value / 10>() + regular<Value % 10>();
}
} // namespace units::detail
+185
View File
@@ -0,0 +1,185 @@
// 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>
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...>;
};
}
template<TypeList List, typename... Types>
using type_list_push_front = 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...>;
};
}
template<TypeList List, typename... Types>
using type_list_push_back = detail::type_list_push_back_impl<List, Types...>::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>
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 = conditional<Idx < N,
typename type_list_push_front_impl<typename base::first_list, T>::type,
typename base::first_list>;
using second_list = conditional<Idx < N,
typename base::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 = split::first_list;
using second_list = 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, 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>
struct type_list_merge_sorted_impl<List<Lhs1, LhsRest...>, List<Rhs1, RhsRest...>, Pred> {
using type = conditional<
Pred<Lhs1, Rhs1>::value,
typename type_list_push_front_impl<typename type_list_merge_sorted_impl<List<LhsRest...>, List<Rhs1, RhsRest...>, Pred>::type, Lhs1>::type,
typename type_list_push_front_impl<typename type_list_merge_sorted_impl<List<Lhs1, LhsRest...>, List<RhsRest...>, Pred>::type, Rhs1>::type>;
};
}
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;
// 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 = 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;
};
}
template<TypeList List, template<typename, typename> typename Pred>
using type_list_sort = detail::type_list_sort_impl<List, Pred>::type;
} // namespace units
+78
View File
@@ -0,0 +1,78 @@
// 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 <type_traits>
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 = detail::conditional_impl<B>::template type<T, F>;
// is_instantiation
namespace detail {
template<typename T, template<typename...> typename Type>
inline constexpr bool is_instantiation_impl = false;
template<typename... Params, template<typename...> typename Type>
inline constexpr bool is_instantiation_impl<Type<Params...>, Type> = true;
} // namespace detail
template<typename T, template<typename...> typename Type>
inline constexpr bool is_instantiation = detail::is_instantiation_impl<T, Type>;
// is_derived_from_instantiation
namespace detail {
template<template<typename...> typename Type>
struct is_derived_from_instantiation_impl {
template<typename... Params>
static constexpr std::true_type check_base(const Type<Params...>&);
static constexpr std::true_type check_base(...);
};
} // namespace detail
template<typename T, template<typename...> typename Type>
inline constexpr bool is_derived_from_instantiation = decltype(detail::is_derived_from_instantiation_impl<Type>::check_base(std::declval<T>()))::value;
} // namespace units