Эх сурвалжийг харах

feat(libstdc++): add at and [] to map

greatbridf 1 жил өмнө
parent
commit
bc841ee42e

+ 8 - 0
gblibstdc++/include/bits/rbtree

@@ -23,6 +23,14 @@ struct rbtree {
         constexpr node(T&& val)
             : parent {}, left {}, right {}
             , value { std::move(val) } , color {node_color::RED} {}
+        
+        template <typename... Args, std::enable_if_t<
+            (sizeof...(Args) > 1)
+            || !(... && std::is_same_v<T, std::remove_cvref_t<Args>>)
+        , bool> = true>
+        constexpr node(Args&&... args)
+            : parent {}, left {}, right {}
+            , value { std::forward<Args>(args)... }, color { node_color::RED } {}
 
         constexpr node* grandparent(void) const
         { return this->parent->parent; }

+ 55 - 0
gblibstdc++/include/map

@@ -4,6 +4,8 @@
 #include <bits/rbtree>
 #include <functional>
 #include <memory>
+#include <tuple>
+#include <type_traits>
 #include <utility>
 #include <cstddef>
 
@@ -131,6 +133,18 @@ public:
     __GBLIBCPP_CONSTEXPR
     const_iterator find(const Key& key) const { return tree.find(key); }
 
+    // if the container does not have an element with
+    // the specified key, it should throw an exception
+    // TODO: exceptions
+    __GBLIBCPP_CONSTEXPR
+    T& at(const Key& key) { return *find(key); }
+
+    // if the container does not have an element with
+    // the specified key, it should throw an exception
+    // TODO: exceptions
+    __GBLIBCPP_CONSTEXPR
+    const T& at(const Key& key) const { return *find(key); }
+
     __GBLIBCPP_CONSTEXPR
     std::pair<iterator, bool> insert(const value_type& value)
     { return tree.insert(value); }
@@ -138,6 +152,12 @@ public:
     std::pair<iterator, bool> insert(value_type&& value)
     { return tree.insert(std::move(value)); }
 
+    template <typename Pair>
+    __GBLIBCPP_CONSTEXPR
+    std::enable_if_t<std::is_constructible_v<value_type, Pair&&>,
+        std::pair<iterator, bool>> insert(Pair&& p)
+    { return emplace(std::forward<Pair>(p)); }
+
     template <typename InputIter>
     __GBLIBCPP_CONSTEXPR
     void insert(InputIter first, InputIter last)
@@ -147,9 +167,44 @@ public:
     }
 
     template <typename... Args>
+    __GBLIBCPP_CONSTEXPR
     std::pair<iterator, bool> emplace(Args&&... args)
     { return tree.emplace(std::forward<Args>(args)...); }
 
+    template <typename... Args>
+    __GBLIBCPP_CONSTEXPR
+    std::pair<iterator, bool> try_emplace(const Key& key, Args&&... args)
+    {
+        auto iter = find(key);
+        if (iter)
+            return { iter, false };
+        return emplace(
+            std::piecewise_construct,
+            std::forward_as_tuple(key),
+            std::forward_as_tuple(std::forward<Args>(args)...));
+    }
+
+    template <typename... Args>
+    __GBLIBCPP_CONSTEXPR
+    std::pair<iterator, bool> try_emplace(Key&& key, Args&&... args)
+    {
+        auto iter = find(key);
+        if (iter)
+            return { iter, false };
+        return emplace(
+            std::piecewise_construct,
+            std::forward_as_tuple(std::move(key)),
+            std::forward_as_tuple(std::forward<Args>(args)...));
+    }
+
+    __GBLIBCPP_CONSTEXPR
+    T& operator[](const Key& key)
+    { return try_emplace(key).first->second; }
+
+    __GBLIBCPP_CONSTEXPR
+    T& operator[](Key&& key)
+    { return try_emplace(std::move(key)).first->second; }
+
     __GBLIBCPP_CONSTEXPR
     iterator erase(iterator pos) noexcept { return tree.erase(pos); }
     __GBLIBCPP_CONSTEXPR

+ 1 - 0
gblibstdc++/include/set

@@ -122,6 +122,7 @@ public:
     }
 
     template <typename... Args>
+    __GBLIBCPP_CONSTEXPR
     std::pair<iterator, bool> emplace(Args&&... args)
     { return tree.emplace(std::forward<Args>(args)...); }
 

+ 65 - 11
gblibstdc++/include/tuple

@@ -55,9 +55,47 @@ struct tuple_size<std::tuple<Types...>>
 
 namespace __helpers {
 
+template <std::size_t I, typename... Types>
+class tuple_impl;
+
+template <>
+class tuple_impl<0> {
+    template <std::size_t, 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&&;
+
+    template <std::size_t> constexpr void _getl(void) const = delete;
+    template <std::size_t> constexpr void _getr(void) const = delete;
+public:
+    constexpr tuple_impl() noexcept = default;
+    
+    constexpr tuple_impl(const tuple_impl& arg) noexcept = default;
+    constexpr tuple_impl(tuple_impl&& arg) noexcept = default;
+
+    template <typename... UTypes>
+    constexpr tuple_impl(const std::tuple<UTypes...>& other) = delete;
+    template <typename... UTypes>
+    constexpr tuple_impl(std::tuple<UTypes...>&& other) = delete;
+    
+    constexpr tuple_impl& operator=(const tuple_impl& other) noexcept = default;
+    constexpr tuple_impl& operator=(tuple_impl&& other) noexcept = default;
+};
+
 template <std::size_t I, typename Type, typename... Types>
-class tuple_impl {
-    template <std::size_t, typename, typename...>
+class tuple_impl<I, Type, Types...> {
+    template <std::size_t, typename...>
     friend class tuple_impl;
 
     template <std::size_t J, typename... UTypes>
@@ -139,7 +177,7 @@ public:
 
 template <std::size_t I, typename Type>
 class tuple_impl<I, Type> {
-    template <std::size_t, typename, typename...>
+    template <std::size_t, typename...>
     friend class tuple_impl;
 
     template <std::size_t J, typename... UTypes>
@@ -157,14 +195,30 @@ class tuple_impl<I, Type> {
 
     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); }
+    template <std::size_t J>
+    constexpr Type& _getl(void)
+    {
+        static_assert(J == I);
+        return val;
+    }
+    template <std::size_t J>
+    constexpr Type const& _getl(void) const
+    {
+        static_assert(J == I);
+        return val;
+    }
+    template <std::size_t J>
+    constexpr Type&& _getr(void)
+    {
+        static_assert(J == I);
+        return std::move(val);
+    }
+    template <std::size_t J>
+    constexpr Type const&& _getr(void) const
+    {
+        static_assert(J == I);
+        return std::move(val);
+    }
 
 public:
     constexpr tuple_impl()