mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-25 22:14:37 +00:00
252 lines
6.8 KiB
Plaintext
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));
|
|
}
|
|
} |