{"id":13730641,"url":"https://github.com/orlp/devector","last_synced_at":"2025-03-21T22:32:16.943Z","repository":{"id":24702122,"uuid":"28113561","full_name":"orlp/devector","owner":"orlp","description":"Resizable contiguous sequence container with fast appends on either end.","archived":false,"fork":false,"pushed_at":"2017-01-28T12:32:46.000Z","size":142,"stargazers_count":37,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-18T05:51:18.559Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"zlib","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/orlp.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-12-17T00:32:48.000Z","updated_at":"2023-09-08T16:53:01.000Z","dependencies_parsed_at":"2022-08-06T03:01:04.616Z","dependency_job_id":null,"html_url":"https://github.com/orlp/devector","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orlp%2Fdevector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orlp%2Fdevector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orlp%2Fdevector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orlp%2Fdevector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/orlp","download_url":"https://codeload.github.com/orlp/devector/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244880448,"owners_count":20525507,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T02:01:17.522Z","updated_at":"2025-03-21T22:32:16.656Z","avatar_url":"https://github.com/orlp.png","language":"C++","readme":"## Warning: `devector` is not finished yet and the implementation is currently an incomplete WIP.\n\n`devector` - a resizable contiguous sequence container with fast appends on either end\n======================================================================================\n\nUnlike `std::vector`, `devector` can have free capacity both before and after the elements. This\nenables efficient implementation of methods that modify the `devector` at the front. Anything a\n`std::vector` can do, a `devector` can as well. `devector`s available methods are a superset of\nthose of `std::vector` with identical behaviour, barring a couple of iterator invalidation\nguarantees that differ. The overhead for `devector` is one extra pointer per container.\n`sizeof(devector) == 4*sizeof(T*)` as opposed to the general implementation of `sizeof(std::vector)\n== 3*sizeof(T*)`. Also, `devector\u003cbool\u003e` is not specialized.\n\nWhenever `devector` requires more free space at an end it applies the following allocation strategy:\n\n 1. Halve the amount of free space that will be left on the other end after the operation and\n    calculate how much free space we want on this end after the operation.\n \n        new_free_other = free_other / 2\n        new_free_this = size() \u003e= 16 ? size() / 3 : size()\n \n 2. If there isn't enough total memory to fit `new_free_other + size() + new_free_this`, then\n    allocate more memory using an exponential factor of 1.5 with doubling for small sizes:\n \n        new_mem = old_mem \u003e= 16 ? old_mem * 1.5 : old_mem * 2\n \n 3. Move the elements into the appropriate memory location, leaving `new_free_other` and\n    `new_free_this` free space at the ends. If new memory was allocated deallocate the old\n    memory.\n\nNote that not every request for more space results in an reallocation. If half of the free space of\nthe other side is enough to satisfy the needs of this side the elements are simply moved.\n\nConstantly halving the amount of free space on the side that it is not used on prevents wasted\nspace. In the worst case where you push at one end and pop at the other (FIFO), memory is bounded to\n_5n/3_. This is because free space on the output end is constantly halved, but only `size() / 3`\nfree space is required on the input end.\n\nTypedefs\n--------\n\n    typedef T                                      value_type;\n    typedef Allocator                              allocator_type;\n    typedef typename alloc_traits::size_type       size_type;\n    typedef typename alloc_traits::difference_type difference_type;\n    typedef typename alloc_traits::pointer         pointer;\n    typedef typename alloc_traits::const_pointer   const_pointer;\n    typedef T\u0026                                     reference;\n    typedef const T\u0026                               const_reference;\n    typedef pointer                                iterator;\n    typedef const_pointer                          const_iterator;\n    typedef std::reverse_iterator\u003citerator\u003e        reverse_iterator;\n    typedef std::reverse_iterator\u003cconst_iterator\u003e  const_reverse_iterator;\n\nAll these typedefs are the same as for std::vector.\n    \nConstruction/Assignment/Swapping/Destructor\n-------------------------------------------\n    \n    ~devector() noexcept;\n    devector() noexcept(std::is_nothrow_default_constructible\u003cAllocator\u003e::value);\n    explicit devector(const Allocator\u0026 alloc) noexcept;\n    explicit devector(size_type n, const Allocator\u0026 alloc = Allocator());\n    devector(size_type n, const T\u0026 value, const Allocator\u0026 alloc = Allocator());\n    template\u003cclass InputIterator\u003e\n        devector(InputIterator first, InputIterator last,\n                 const Allocator\u0026 alloc = Allocator());\n    devector(const devector\u003cT\u003e\u0026 other);\n    devector(const devector\u003cT\u003e\u0026 other, const Allocator\u0026 alloc);\n    devector(devector\u003cT\u003e\u0026\u0026 other) noexcept;\n    devector(devector\u003cT\u003e\u0026\u0026 other, const Allocator\u0026 alloc);\n    devector(std::initializer_list\u003cT\u003e il, const Allocator\u0026 alloc = Allocator());\n    devector\u003cT\u003e\u0026 operator=(const devector\u003cT\u003e\u0026 other);\n    devector\u003cT\u003e\u0026 operator=(devector\u003cT\u003e\u0026\u0026 other) noexcept(/* See below.. */);\n    devector\u003cT\u003e\u0026 operator=(std::initializer_list\u003cT\u003e il);\n    template\u003cclass InputIterator\u003e\n        void assign(InputIterator first, InputIterator last);\n    void assign(size_type n, const T\u0026 t);\n    void assign(std::initializer_list\u003cT\u003e il);\n\nAll these operations have the exact same syntax and semantics as std::vector. The move assignment\noperator is marked `noexcept` if the allocator should propagate on move assignment.\n\nGetters\n-------\n\n    allocator_type         get_allocator()         const noexcept;\n    iterator               begin()                       noexcept;\n    const_iterator         begin()                 const noexcept;\n    iterator               end()                         noexcept;\n    const_iterator         end()                   const noexcept;\n    reverse_iterator       rbegin()                      noexcept;\n    const_reverse_iterator rbegin()                const noexcept;\n    reverse_iterator       rend()                        noexcept;\n    const_reverse_iterator rend()                  const noexcept;\n    const_iterator         cbegin()                const noexcept;\n    const_iterator         cend()                  const noexcept;\n    const_reverse_iterator crbegin()               const noexcept;\n    const_reverse_iterator crend()                 const noexcept;\n    reference              front()                       noexcept;\n    const_reference        front()                 const noexcept;\n    reference              back()                        noexcept;\n    const_reference        back()                  const noexcept;\n    T*                     data()                        noexcept;\n    const T*               data()                  const noexcept;\n    reference              operator[](size_type i)       noexcept;\n    const_reference        operator[](size_type i) const noexcept;\n    reference              at(size_type i);\n    const_reference        at(size_type i)         const;\n    size_type              max_size()              const noexcept;\n    size_type              size()                  const noexcept;\n    bool                   empty()                 const noexcept;\n\nAll these operations have the exact same syntax and semantics as `std::vector`. The only difference\nis that some functions have been marked `noexcept`, even though the standard doesn't require it.\n\n    size_type capacity()       const noexcept;\n    size_type capacity_front() const noexcept;\n    size_type capacity_back()  const noexcept;\n    \nThe function `capacity` is an alias for `capacity_back`. `capacity_back` returns the number of\nelements in the container plus the amount of elements that can fit in the free space at the back.\n`capacity_front` does the exact same except for the free space at the front. This means that the\ntotal size of allocated memory is `sizeof(T) * (capacity_front() + capacity_back() - size())`.\n\nModifiers\n---------\nThe following functions are also required to be `MoveAssignable` in addition to the limitations put\nforth by `std::vector`: `emplace_back`, `push_back`, `emplace_front`, `push_front`, `resize`,\n`resize_back`, `resize_front`.\n\n    \n    void swap(devector\u003cT\u003e\u0026 other) noexcept(/* See below. */);\n    void shrink_to_fit();\n    void clear() noexcept;\n    template\u003cclass... Args\u003e\n        void emplace_back(Args\u0026\u0026... args);\n    void push_back(const T\u0026 x);\n    void push_back(T\u0026\u0026 x);\n    void pop_back();\n\nAll these operations have the exact same syntax and semantics as `std::vector`. The `noexcept`\nspecifier for `swap` is only false if the allocator must be propagated on swap and it can not be\nswapped without exceptions.\n\n    template\u003cclass... Args\u003e\n        void emplace_front(Args\u0026\u0026... args);\n    void push_front(const T\u0026 x);\n    void push_front(T\u0026\u0026 x);\n\nPrepends an element to the container. If the new `size()` is greater than `capacity_front()` all\nreferences and iterators (including the past-the-end iterator) are invalidated. Otherwise all\niterators and references remain valid. The behaviour on exceptions is the same as\n`push_back`/`emplace_back`.\n\n    void pop_front();\n\nRemoves the first element of the container. Calling `pop_front` on an empty container is undefined.\nNo iterators or references except `front()` and `begin()` are invalidated.\n\n    void reserve(size_type n);\n    void reserve(size_type new_front, size_type new_back);\n    void reserve_front(size_type n);\n    void reserve_back(size_type n);\n    \nThe single argument `reserve` is an alias for `reserve_back`. `reserve_back` has the exact same\nsemantics as `std::vector`s `reserve`. `reserve_front` does the same as `reserve_back` except it\ninfluences `capacity_front()` rather than the capacity at the back. The two argument `reserve` has\nthe same behaviour as two calls to respectively `reserve_front` and `reserve_back`, but is more\nefficient by doing at most one reallocation.\n\n    void resize(size_type n);\n    void resize(size_type n, const T\u0026 t);\n    void resize_back(size_type n);\n    void resize_back(size_type n, const T\u0026 t);\n    void resize_front(size_type n);\n    void resize_front(size_type n, const T\u0026 t);\n\n`resize` is an alias for `resize_back` and has the exact same semantics as `std::vector`.\n`resize_front` is the same as `resize_back` except that it resizes the container with\n`push_front`/`pop_front` rather than `push_back`/`pop_back`.\n\n    template\u003cclass... Args\u003e\n        iterator emplace(const_iterator position, Args\u0026\u0026... args);\n    iterator insert(const_iterator position, const T\u0026 t);\n    iterator insert(const_iterator position, T\u0026\u0026 t);\n    iterator insert(const_iterator position, size_type n, const T\u0026 t);\n    iterator insert(const_iterator position, std::initializer_list\u003cT\u003e il);\n    template\u003cclass InputIterator\u003e\n        iterator insert(const_iterator position, InputIterator first, InputIterator last);\n\nAll these operations have the same semantics as `std::vector`, except for the iterators/references\nthat get invalidated by these operations. If `position - begin() \u003c size() / 2` then only the\niterators/references after the insertion point remain valid (including the past-the-end iterator).\nOtherwise only the iterators/references before the insertion point remain valid.\n\n    iterator erase(const_iterator position);\n\nBehaves the same as as `std::vector`, except for which iterators/references get invalidated. If\n`position - begin() \u003c size() / 2` then all iterators and references at or before `position` are\ninvalidated. Otherwise all iterators and references at or after (including `end()`) `position` are\ninvalidated.\n\n    iterator erase(const_iterator first, const_iterator last);\n\nBehaves the same as as `std::vector`, except for which iterators/references get invalidated. If\n`first - begin() \u003c end() - last` then all iterators and references at or before `last` are\ninvalidated. Otherwise all iterators and references at or after (including `end()`) `first` are\ninvalidated.\n\nLastly, `devector` has lexical comparison operator overloads and `swap` defined in its namespace\njust like `std::vector`.\n","funding_links":[],"categories":["C++"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Forlp%2Fdevector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Forlp%2Fdevector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Forlp%2Fdevector/lists"}