2024-05-18 07:42:01 +03:00

252 lines
6.8 KiB
Plaintext

/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <type_traits>
#include <algorithm>
#include <tuple>
namespace std
{
struct piecewise_construct_t
{
explicit piecewise_construct_t() = default;
};
inline constexpr std::piecewise_construct_t piecewise_construct{};
template <typename T>
typename std::remove_reference<T>::type &&move(T &&arg)
{
return static_cast<typename std::remove_reference<T>::type &&>(arg);
}
template <typename T>
void __utility_swap(T &a, T &b)
{
T temp = std::move(a);
a = std::move(b);
b = std::move(temp);
}
template <class T, T... Ints>
class integer_sequence
{
public:
typedef T value_type;
static constexpr std::size_t size() noexcept { return sizeof...(Ints); }
};
template <std::size_t... Ints>
using index_sequence = std::integer_sequence<std::size_t, Ints...>;
template <class T, T N>
using make_integer_sequence = std::integer_sequence<T, N>;
template <std::size_t N>
using make_index_sequence = std::make_integer_sequence<std::size_t, N>;
template <class... T>
using index_sequence_for = std::make_index_sequence<sizeof...(T)>;
template <class T>
constexpr T &&forward(std::remove_reference_t<T> &t) noexcept
{
return static_cast<T &&>(t);
}
template <class T>
constexpr T &&forward(std::remove_reference_t<T> &&t) noexcept
{
static_assert(!std::is_lvalue_reference<T>::value, "Can't forward an rvalue as an lvalue.");
return static_cast<T &&>(t);
}
template <typename T1, typename T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
first_type first;
second_type second;
template <typename U1 = T1,
typename U2 = T2,
typename std::enable_if<std::is_default_constructible<U1>::value &&
std::is_default_constructible<U2>::value,
int>::type = true>
constexpr pair()
: first(),
second()
{
}
template <typename U1 = T1,
typename U2 = T2,
typename std::enable_if<!std::is_default_constructible<U1>::value ||
!std::is_default_constructible<U2>::value,
int>::type = false>
explicit constexpr pair()
: first(),
second()
{
}
template <typename U1 = T1,
typename U2 = T2,
typename std::enable_if<std::is_copy_constructible<U1>::value &&
std::is_copy_constructible<U2>::value,
int>::type = true>
constexpr pair(const T1 &x, const T2 &y)
: first(x),
second(y)
{
}
template <typename U1 = T1,
typename U2 = T2,
typename std::enable_if<!std::is_copy_constructible<U1>::value ||
!std::is_copy_constructible<U2>::value,
int>::type = false>
explicit constexpr pair(const T1 &x, const T2 &y)
: first(x),
second(y)
{
}
template <typename U1 = T1,
typename U2 = T2,
typename std::enable_if<std::is_move_constructible<U1>::value &&
std::is_move_constructible<U2>::value,
int>::type = true>
constexpr pair(U1 &&x, U2 &&y)
: first(std::forward<U1>(x)),
second(std::forward<U2>(y))
{
}
template <typename U1 = T1,
typename U2 = T2,
typename std::enable_if<!std::is_move_constructible<U1>::value ||
!std::is_move_constructible<U2>::value,
int>::type = false>
explicit constexpr pair(T1 &&x, T2 &&y)
: first(std::forward<T1>(x)),
second(std::forward<T2>(y)){};
template <typename U1 = T1,
typename U2 = T2,
typename std::enable_if<std::is_copy_constructible<U1>::value &&
std::is_copy_constructible<U2>::value,
int>::type = true>
constexpr pair(const pair<U1, U2> &p)
: first(p.first),
second(p.second)
{
}
template <typename U1 = T1,
typename U2 = T2,
typename std::enable_if<!std::is_copy_constructible<U1>::value ||
!std::is_copy_constructible<U2>::value,
int>::type = false>
explicit constexpr pair(const pair<U1, U2> &p)
: first(p.first),
second(p.second)
{
}
template <typename U1 = T1,
typename U2 = T2,
typename std::enable_if<std::is_move_constructible<U1>::value &&
std::is_move_constructible<U2>::value,
int>::type = true>
constexpr pair(pair<U1, U2> &&p)
: first(std::forward<U1>(p.first)),
second(std::forward<U2>(p.second))
{
}
template <typename U1 = T1,
typename U2 = T2,
typename std::enable_if<!std::is_move_constructible<U1>::value ||
!std::is_move_constructible<U2>::value,
int>::type = false>
explicit constexpr pair(pair<U1, U2> &&p)
: first(std::forward<U1>(p.first)),
second(std::forward<U2>(p.second))
{
}
template <class... Args1, class... Args2>
constexpr pair(std::piecewise_construct_t, std::tuple<Args1...> first_args, std::tuple<Args2...> second_args)
: pair(first_args, second_args, std::index_sequence_for<Args1...>(), std::index_sequence_for<Args2...>())
{
}
pair(const pair &p) = default;
pair(pair &&p) = default;
constexpr pair &operator=(const pair &other)
{
first = other.first;
second = other.second;
return *this;
}
template <class U1, class U2>
constexpr pair &operator=(const pair<U1, U2> &other)
{
first = other.first;
second = other.second;
return *this;
}
constexpr pair &operator=(pair &&other) noexcept(std::is_nothrow_move_assignable<T1>::value && std::is_nothrow_move_assignable<T2>::value)
{
first = std::move(other.first);
second = std::move(other.second);
return *this;
}
template <class U1, class U2>
constexpr pair &operator=(pair<U1, U2> &&p)
{
first = std::forward<U1>(p.first);
second = std::forward<U2>(p.second);
return *this;
}
constexpr void swap(pair &other) noexcept(std::is_nothrow_swappable_v<first_type> && std::is_nothrow_swappable_v<second_type>)
{
__utility_swap(first, other.first);
__utility_swap(second, other.second);
}
};
template <class T1, class T2>
std::pair<typename std::decay<T1>::type, typename std::decay<T2>::type> make_pair(T1 &&t, T2 &&u)
{
typedef typename std::decay<T1>::type first_type;
typedef typename std::decay<T2>::type second_type;
typedef pair<first_type, second_type> pair_type;
return pair_type(std::forward<T1>(t), std::forward<T2>(u));
}
}