forked from mpusz/mp-units
Text formatting enabled + directory tree refactoring
This commit is contained in:
+72
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
Reference in New Issue
Block a user