|
libbmb
Modern implementation of STL
|
libbmb is a header only DSA library written using modern C++. It implements significant STL functionality and extends it. The library's containers are AllocatorAware with strong exception guarantee. The key features of this realization are code readability, rich documentation, and modern view to the code design.
All documentation is available here.
Why do we need one more DSA library while there'are STL, Boost, Abseil and many other great solutions? There are several reasons for that:
CMakeLists.txt: shell add_subdirectory(libbmb) target_link_libraries(*your_target* PRIVATE libbmb) libbmb uses cmake's interface, so when linking you'll automatically get include directories.CMakeLists.txt, and run: shell make test This will automatically install gtest and run tests with valgrind checks. clang. To build with gcc run: shell make test_gcc Note: if you use clangd as a language server, adjust the include path in the .clangd config file. Following sections contain details about implemented and planned functionality, C++ standard compatibility, reasons why there's a deviation from the standard, and some other useful notes.
Declaration and definition of templates.
Since C++ obligates to write boilerplate template types like:
it is painful to separately declare and define template class methods. Boilerplate can be avoided using strange looking macroses like:
The desicion was made to define methods inside a class. Documentation and definition at the same place. If you don't like this - every modern IDE supports code wrapping, so collapse all definitions by default.
.excalidraw format and can be viewed and modified in the official website without registration. Note: the schemas may slightly differ from the actual implementation, but the general concepts are preserved.There are changes in the allocator's design. std::allocator analog here is PrimitiveAllocator. It isn't a template. The template parameter in class only creates pain and rebind semantics. Instead, every allocator's function marked as a template. Thus, each allocator must define at least allocate method as a template(other methods can use template type deduction, so may be non-templated).
allocate method must be a template.Due to the C++ rules, allocate call will look weird: ```c++ using AllocTraits = bmb::AllocatorTraits<SomeAllocator>; SomeAllocator alloc;
auto ptr = AllocTraits::template allocate<T>(alloc, 10);
``` Meanwhile other methods usage the same as STL ones.
Also the allocator's copy and move semantics changed:
STL differentiates allocators copying/moving as value type(like string, vector and any other) and allocators copying/moving as container's fields. Therefore every container must consult a allocator what to do while copying/moving. libbmb preserve only the second semantics, so now each allocator must define copy/move c-tors/assignment operators with appropriate semantics. propogate_on_container_... and select_on_container_copy_construction are not used.
iterator_traits are not implemented, since there's no real need for them - every iterator still must define category, value_type, etc. However traits support raw pointer and have rules for defining missing typedefs. There is real need for traits for raw pointers, otherwise this is not possible use general algorithms(like std::copy) for pointers. Now, as in STL, every Iter::some type must be IteratorTraits<Iter>::some type.
This is a classic implementation of STL vector. It suports all original vector methods except shrink_to_fit and insert. They will be added later. The major difference from the STL one is an exception safety.
For methods like pushBack and reserve conditional safety is provided:
For the reallocation the move constructor is always chosen. If it throws, Vector destroyes all moved elements, leaving the original array with some empty elements and elements, that weren't moved. There is the basic guarantee. Otherwise the strong guarantee.
Meanwhile, STL's version will choose move c-tor only if it is marked as noexcept.
Currently, there is a problem: the provided template type must not delete move c-tor explicitly, since forwarding and moving will stop compile(reserve, pushBack, emplaceBack). This can be fixed by concepts or SFINAE. Highly likely this will not be fixed due to the redundancy. Modern code must(at least from the author's point of view) either define both copy and move c-tor(may just call copy one if it isn't able to move) or doesn't define them at all.
concept: 1
sources: 1, 2, 3
tests: 1
Extended implementation of singly linked list. Conceptually, have head node on the stack, allocates other nodes in heap. But introduces several modes, that affect class instanse size and performance:
Modes 2 and 3 can be used separately or simultaneously. Simultaneous use of 2 and 3 is preffered for most cases. Note that there is only one definition of the class, modes are controlled via 2 additional template bool parameters and internally via if constexpr, so, if you don't need additional functionality, you wont get any useless overhead. For convenience, there are using-declarations: LListTiny, LListFat, LListFastSize, LListFastLast.
Some iterator traits will not be implemented, since c++20 concepts may almost completely replace them. Now implemented the most important traits. Support will be extended with the growth of the codebase.
Now implemented the most important concepts. Support will be extended with the growth of the codebase.