Parcourir la source

feat(libstdc++): tuple

greatbridf il y a 1 an
Parent
commit
c4bd0eb20e

+ 373 - 0
gblibstdc++/include/tuple

@@ -0,0 +1,373 @@
+#ifndef __GBLIBCPP_TUPLE__
+#define __GBLIBCPP_TUPLE__
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+#include <functional>
+
+namespace std {
+
+template <std::size_t I, typename T>
+struct tuple_element;
+
+template <std::size_t I, typename T>
+using tuple_element_t = typename tuple_element<I, T>::type;
+
+template <typename T>
+struct tuple_size;
+
+template <typename T>
+inline constexpr std::size_t tuple_size_v = tuple_size<T>::value;
+
+template <std::size_t I, typename T>
+struct tuple_element<I, const T> {
+    using type = std::add_const_t<tuple_element_t<I, T>>;
+};
+template <std::size_t I, typename T>
+struct tuple_element<I, volatile T> {
+    using type = std::add_volatile_t<tuple_element_t<I, T>>;
+};
+template <std::size_t I, typename T>
+struct tuple_element<I, const volatile T> {
+    using type = std::add_cv_t<tuple_element_t<I, T>>;
+};
+
+namespace __helpers {
+
+template <typename T, typename = void>
+struct __const_tuple_size {};
+
+template <typename T>
+struct __const_tuple_size<T, void_t<decltype(std::tuple_size<T>::value)>>
+    : std::integral_constant<std::size_t, std::tuple_size<T>::value> {};
+
+} // namespace __helpers
+
+template <typename T>
+struct tuple_size<const T> : __helpers::__const_tuple_size<T> {};
+
+template <typename... Types>
+class tuple;
+
+template <std::size_t I, typename Type, typename... Types>
+struct tuple_element<I, std::tuple<Type, Types...>>
+    : tuple_element<I-1, std::tuple<Types...>> {};
+
+template <typename Type, typename... Types>
+struct tuple_element<0, std::tuple<Type, Types...>> { using type = Type; };
+
+template <typename... Types>
+struct tuple_size<std::tuple<Types...>>
+    : std::integral_constant<std::size_t, sizeof...(Types)> {};
+
+template <std::size_t I, typename... Types>
+constexpr auto get(std::tuple<Types...>& tpl) noexcept
+    -> tuple_element_t<I, std::tuple<Types...>>&
+{ return tpl.template _getl<I>(); }
+
+template <std::size_t I, typename... Types>
+constexpr auto get(std::tuple<Types...>&& tpl) noexcept
+    -> tuple_element_t<I, std::tuple<Types...>>&&
+{ return tpl.template _getr<I>(); }
+
+template <std::size_t I, typename... Types>
+constexpr auto get(const std::tuple<Types...>& tpl) noexcept
+    -> tuple_element_t<I, std::tuple<Types...>> const&
+{ return tpl.template _getl<I>(); }
+
+template <std::size_t I, typename... Types>
+constexpr auto get(const std::tuple<Types...>&& tpl) noexcept
+    -> tuple_element_t<I, std::tuple<Types...>> const&&
+{ return tpl.template _getr<I>(); }
+
+namespace __helpers {
+
+template <std::size_t I, typename Type, typename... Types>
+class tuple_impl {
+    template <std::size_t, typename, typename...>
+    friend class tuple_impl;
+
+    template <std::size_t J, typename... UTypes>
+    friend constexpr auto std::get(std::tuple<UTypes...>& tpl) noexcept
+        -> tuple_element_t<J, std::tuple<UTypes...>>&;
+    template <std::size_t J, typename... UTypes>
+    friend constexpr auto std::get(std::tuple<UTypes...>&& tpl) noexcept
+        -> tuple_element_t<J, std::tuple<UTypes...>>&&;
+    template <std::size_t J, typename... UTypes>
+    friend constexpr auto std::get(const std::tuple<UTypes...>& tpl) noexcept
+        -> tuple_element_t<J, std::tuple<UTypes...>> const&;
+    template <std::size_t J, typename... UTypes>
+    friend constexpr auto std::get(const std::tuple<UTypes...>&& tpl) noexcept
+        -> tuple_element_t<J, std::tuple<UTypes...>> const&&;
+
+    Type val;
+    tuple_impl<I+1, Types...> next;
+
+    template <std::size_t J>
+    constexpr auto& _getl(void)
+    {
+        if constexpr (I == J)
+            return val;
+        else
+            return next.template _getl<J>();
+    }
+
+    template <std::size_t J>
+    constexpr const auto& _getl(void) const
+    {
+        if constexpr (I == J)
+            return val;
+        else
+            return next.template _getl<J>();
+    }
+
+    template <std::size_t J>
+    constexpr auto&& _getr(void)
+    {
+        if constexpr (I == J)
+            return std::move(val);
+        else
+            return std::move(next.template _getr<J>());
+    }
+
+    template <std::size_t J>
+    constexpr const auto&& _getr(void) const
+    {
+        if constexpr (I == J)
+            return std::move(val);
+        else
+            return std::move(next.template _getr<J>());
+    }
+
+public:
+    constexpr tuple_impl()
+        : val(), next() {}
+    
+    constexpr tuple_impl(const tuple_impl& arg) = default;
+    constexpr tuple_impl(tuple_impl&& arg) = default;
+
+    constexpr tuple_impl(const Type& val, const Types&... vals)
+        : val(val), next(vals...) {}
+    
+    template <typename UType, typename... UTypes>
+    constexpr tuple_impl(UType&& val, UTypes&&... vals)
+        : val(std::forward<UType>(val)), next(std::forward<UTypes>(vals)...) {}
+
+    template <typename... UTypes>
+    constexpr tuple_impl(const std::tuple<UTypes...>& other)
+        : val(std::get<I>(other)), next(other) {}
+    template <typename... UTypes>
+    constexpr tuple_impl(std::tuple<UTypes...>&& other)
+        : val(std::get<I>(other)), next(std::move(other)) {}
+    
+    constexpr tuple_impl& operator=(const tuple_impl& other) = default;
+    constexpr tuple_impl& operator=(tuple_impl&& other) = default;
+};
+
+template <std::size_t I, typename Type>
+class tuple_impl<I, Type> {
+    template <std::size_t, typename, typename...>
+    friend class tuple_impl;
+
+    template <std::size_t J, typename... UTypes>
+    friend constexpr auto std::get(std::tuple<UTypes...>& tpl) noexcept
+        -> tuple_element_t<J, std::tuple<UTypes...>>&;
+    template <std::size_t J, typename... UTypes>
+    friend constexpr auto std::get(std::tuple<UTypes...>&& tpl) noexcept
+        -> tuple_element_t<J, std::tuple<UTypes...>>&&;
+    template <std::size_t J, typename... UTypes>
+    friend constexpr auto std::get(const std::tuple<UTypes...>& tpl) noexcept
+        -> tuple_element_t<J, std::tuple<UTypes...>> const&;
+    template <std::size_t J, typename... UTypes>
+    friend constexpr auto std::get(const std::tuple<UTypes...>&& tpl) noexcept
+        -> tuple_element_t<J, std::tuple<UTypes...>> const&&;
+
+    Type val;
+
+    template <std::size_t>
+    constexpr Type& _getl(void) { return val; }
+    template <std::size_t>
+    constexpr Type const& _getl(void) const { return val; }
+    template <std::size_t>
+    constexpr Type&& _getr(void) { return std::move(val); }
+    template <std::size_t>
+    constexpr Type const&& _getr(void) const { return std::move(val); }
+
+public:
+    constexpr tuple_impl()
+        : val() {}
+    
+    constexpr tuple_impl(const tuple_impl& arg) = default;
+    constexpr tuple_impl(tuple_impl&& arg) = default;
+
+    constexpr tuple_impl(const Type& val) : val(val) {}
+
+    template <typename UType>
+    constexpr tuple_impl(UType&& val) : val(std::forward<UType>(val)) {}
+
+    template <typename... UTypes>
+    constexpr tuple_impl(const std::tuple<UTypes...>& other)
+        : val(std::get<I>(other)) {}
+    template <typename... UTypes>
+    constexpr tuple_impl(std::tuple<UTypes...>&& other)
+        : val(std::get<I>(other)) {}
+
+    constexpr tuple_impl& operator=(const tuple_impl& other) = default;
+    constexpr tuple_impl& operator=(tuple_impl&& other) = default;
+};
+
+} // namespace __helpers
+
+template <typename... Types>
+class tuple : public __helpers::tuple_impl<0, Types...> {
+private:
+    using base = __helpers::tuple_impl<0, Types...>;
+
+    template <typename... UTypes, std::size_t... I>
+    constexpr void __copy_assignment(const tuple<UTypes...>& other, std::index_sequence<I...>)
+    { ((std::get<I>(*this) = std::get<I>(other)), ...); }
+
+    template <typename... UTypes, std::size_t... I>
+    constexpr void __move_assignment(tuple<UTypes...>&& other, std::index_sequence<I...>)
+    { ((std::get<I>(*this) = std::forward<UTypes>(std::get<I>(other))), ...); }
+
+public:
+    constexpr tuple() : base() {}
+
+    constexpr tuple(const Types&... args)
+        : base(args...) {}
+    
+    template <typename... UTypes, enable_if_t<
+        sizeof...(UTypes) == sizeof...(Types)
+        && sizeof...(Types) >= 1
+        && !(sizeof...(Types) == 1 && (... && std::is_same_v<tuple, UTypes>))
+    , bool> = true>
+    constexpr tuple(UTypes&&... args)
+        : base(std::forward<UTypes>(args)...) {}
+
+    template <typename... UTypes>
+    constexpr tuple(const tuple<UTypes...>& other)
+        : base(other) {}
+
+    template <typename... UTypes>
+    constexpr tuple(tuple<UTypes...>&& other)
+        : base(std::move(other)) {}
+    
+    // TODO: std::pair constructors
+
+    tuple(const tuple&) = default;
+    tuple(tuple&&) = default;
+
+    constexpr tuple& operator=(const tuple& other) = default;
+    constexpr tuple& operator=(tuple&& other) = default;
+
+    template <typename... UTypes, enable_if_t<
+        sizeof...(Types) == sizeof...(UTypes)
+        && (... && std::is_assignable_v<Types&, const UTypes&>)
+        , bool> = true>
+    constexpr tuple& operator=(const tuple<UTypes...>& other)
+    {
+        __copy_assignment(other, index_sequence_for<Types...> {});
+        return *this;
+    }
+
+    template <typename... UTypes, enable_if_t<
+        sizeof...(Types) == sizeof...(UTypes)
+        && (... && std::is_assignable_v<Types&, UTypes>)
+        , bool> = true>
+    constexpr tuple& operator=(tuple<UTypes...>&& other)
+    {
+        __move_assignment(std::move(other), index_sequence_for<Types...> {});
+        return *this;
+    }
+
+    constexpr void swap(tuple& other) { std::swap(*this, other); }
+};
+
+template <typename... Types>
+tuple(Types...) -> tuple<Types...>;
+
+namespace __helpers {
+
+struct ignore_t {
+    template <typename T>
+    constexpr void operator=(T&&) const noexcept {}
+};
+
+template <typename _T, typename T = std::decay_t<_T>>
+struct __to_tuple_type { using type = T; };
+
+template <typename _T, typename T>
+struct __to_tuple_type<_T, std::reference_wrapper<T>>
+{ using type = std::add_lvalue_reference_t<T>; };
+
+template <typename T, typename Tuple, std::size_t... I>
+constexpr T make_from_tuple_impl(Tuple&& tpl, std::index_sequence<I...>)
+{
+    return T { std::get<I>(std::forward<Tuple>(tpl))... };
+}
+
+template <typename Func, typename Tuple, std::size_t... I>
+constexpr auto apply_impl(Func&& func, Tuple&& tpl, std::index_sequence<I...>)
+{
+    return std::invoke(
+        std::forward<Func>(func),
+        std::get<I>(std::forward<Tuple>(tpl))...);
+}
+
+} // namespace __helpers
+
+inline constexpr __helpers::ignore_t ignore;
+
+template <typename... Types>
+constexpr void swap(std::tuple<Types...>& lhs, std::tuple<Types...>& rhs)
+    noexcept(noexcept(lhs.swap(rhs)))
+{
+    lhs.swap(rhs);
+}
+
+template <typename... Types>
+constexpr auto make_tuple(Types&&... args)
+    -> std::tuple<typename __helpers::__to_tuple_type<Types>::type...>
+{
+    return std::tuple<typename __helpers::__to_tuple_type<Types>::type...>
+        { std::forward<Types>(args)... };
+}
+
+template <typename... Types>
+constexpr std::tuple<Types&...> tie(Types&... args) noexcept
+{
+    return { args... };
+}
+
+template <typename... Types>
+constexpr std::tuple<Types&&...> forward_as_tuple(Types&&... args) noexcept
+{
+    return { std::forward<Types>(args)... };
+}
+
+template <typename T, typename Tuple>
+constexpr T make_from_tuple(Tuple&& tpl)
+{
+    return __helpers::make_from_tuple_impl<T>(
+        std::forward<Tuple>(tpl),
+        std::make_index_sequence<
+            std::tuple_size_v<std::remove_cvref_t<Tuple>>> {}
+    );
+}
+
+template <typename Func, typename Tuple>
+constexpr decltype(auto) apply(Func&& func, Tuple&& tpl)
+{
+    return __helpers::apply_impl(
+        std::forward<Func>(func), std::forward<Tuple>(tpl),
+        std::make_index_sequence<
+            std::tuple_size_v<std::remove_cvref_t<Tuple>>> {}
+    );
+}
+
+} // namespace std
+
+#endif

+ 18 - 0
gblibstdc++/include/type_traits

@@ -192,6 +192,14 @@ struct is_function<T&&> : public false_type {};
 template <typename T>
 inline constexpr bool is_function_v = is_function<T>::value;
 
+template <typename T>
+struct remove_cvref {
+    using type = remove_cv_t<remove_reference_t<T>>;
+};
+
+template <typename T>
+using remove_cvref_t = typename remove_cvref<T>::type;
+
 template <typename T>
 struct decay {
 private:
@@ -439,6 +447,16 @@ struct invoke_result : __helpers::__invoke_result<Func, void, Args...> {};
 template <class Func, class... Args>
 using invoke_result_t = typename invoke_result<Func, Args...>::type;
 
+template <typename T, typename U, typename = void>
+struct is_assignable : public false_type {};
+
+template <typename T, typename U>
+struct is_assignable<T, U, void_t<
+    decltype(std::declval<T>() = std::declval<U>())>> : public true_type {};
+
+template <typename T, typename U>
+inline constexpr bool is_assignable_v = is_assignable<T, U>::value;
+
 #define __CPP_GREATBRIDF
 #ifdef __CPP_GREATBRIDF
 

+ 27 - 0
gblibstdc++/include/utility

@@ -1,6 +1,8 @@
 #ifndef __GBLIBCPP_UTILITY__
 #define __GBLIBCPP_UTILITY__
 
+#include <cstddef>
+
 namespace std {
 
 namespace __helpers {
@@ -42,6 +44,31 @@ constexpr T exchange(T& dst, U&& val)
     return tmp;
 }
 
+template <typename T>
+constexpr void swap(T& a, T& b)
+{
+    T tmp(std::move(a));
+    a = std::move(b);
+    b = std::move(tmp);
+}
+
+template <typename T, T... Ints>
+struct integer_sequence {
+    static constexpr std::size_t size() noexcept { return sizeof...(Ints); }
+};
+
+template <std::size_t... Indicies>
+using index_sequence = integer_sequence<std::size_t, Indicies...>;
+
+template <std::size_t N, std::size_t... Indicies>
+struct make_index_sequence : public make_index_sequence<N-1, N-1, Indicies...> {};
+
+template <std::size_t... Indicies>
+struct make_index_sequence<0, Indicies...> : public index_sequence<Indicies...> {};
+
+template <typename... Ts>
+using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
+
 } // namespace std
 
 #endif

+ 4 - 4
include/kernel/process.hpp

@@ -180,7 +180,7 @@ public:
         {
             int fd = 0;
 
-            for (auto&& [ item_fd, iter_file ] : arr) {
+            for (auto [ item_fd, iter_file ] : arr) {
                 if (item_fd == fd)
                     ++fd;
             }
@@ -221,9 +221,9 @@ public:
 
         constexpr void dup_all(const filearr& orig)
         {
-            for (auto&& [ fd, file ] : orig.arr) {
-                this->arr.insert(types::make_pair(fd, file));
-                ++file->ref;
+            for (auto [ fd, iter_file ] : orig.arr) {
+                this->arr.insert(types::make_pair(fd, iter_file));
+                ++iter_file->ref;
             }
         }