Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/arturbac/small_vectors
Optimized C++20/23 vectors, strings with in class buffer storage, and utility algorithms
https://github.com/arturbac/small_vectors
basic-string containers expected expected-unexpected interprocess interprocess-communication meta-struct metastruct shared-memory small-vector small-vectors static-vector string strongly-typed strongly-typed-types type-safety unaligned-access utility-library
Last synced: 1 day ago
JSON representation
Optimized C++20/23 vectors, strings with in class buffer storage, and utility algorithms
- Host: GitHub
- URL: https://github.com/arturbac/small_vectors
- Owner: arturbac
- License: mit
- Created: 2022-02-24T10:23:49.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2024-07-17T12:12:41.000Z (4 months ago)
- Last Synced: 2024-08-02T06:12:11.721Z (3 months ago)
- Topics: basic-string, containers, expected, expected-unexpected, interprocess, interprocess-communication, meta-struct, metastruct, shared-memory, small-vector, small-vectors, static-vector, string, strongly-typed, strongly-typed-types, type-safety, unaligned-access, utility-library
- Language: C++
- Homepage:
- Size: 421 KB
- Stars: 9
- Watchers: 2
- Forks: 1
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
- awesome-modern-cpp - small_vectors
README
# small_vectors
![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![CMake](https://github.com/arturbac/fixed_math/workflows/CMake/badge.svg)
![language](https://img.shields.io/badge/language-C%2B%2B20-blue.svg)![language](https://img.shields.io/badge/language-C%2B%2B23-red.svg)C++20,23 utilities library
## Features
- **Static Vector**: Trivially copyable for types that are trivially copyable, enabling compiler optimizations such as `memcpy` for copying operations (since v3.0.3-devel).
- **Address Independence**: static vectors and static string offer in-class storage, making them address-independent and suitable for interprocess data exchange.
- **Dynamic and Custom Sized Storage**: Small vectors support dynamic memory allocation with customizable size types. Static vectors adjust the minimal size type based on the number of elements.
- **Constant Evaluation**: Static vectors can be fully evaluated at compile time for trivial element types.
- **Basic String with Dual Storage**: Provides a basic string implementation with both dynamic and static in-class storage options. The static storage variant is address-independent.
- **Basic Fixed String**: Enables manipulation of constant evaluated string literals.
- **Expected/Unexpected Implementation**: Offers a C++23 standard `expected/unexpected` implementation with monadic operations for C++20 and up.## Minor Utility Features
- **Meta Packed Struct**: Supports bit-packing data with strong typing. Version 2.3.0 introduced signed type support.
- **Strong Type Wrapping**: Allows for the strong type wrapping of primitive types.
- **Unaligned Access**: Functions for memory unaligned access are fully capable of being executed at compile time starting with v2.4.2.## Interprocess Features
- **Fork Wrapper**: Simplifies process spawning with an interface similar to `std::async`.
- **Shared Memory Utilities**: Facilitates the construction and access of data in shared interprocess memory with automated memory access indexing to prevent errors.### examples
#### small_vector and static_vector
```C++#include
//static vector with in buffer class memory for 10 elements
coll::static_vector vec10;//small vector with in buffer class memory for coll::union_min_number_of_elements
coll::small_vector vec10;
//equivalent for std::vector with size type eq size_t and not in class buffer memory
coll::small_vector vec10;```
#### expected/unexpected
```C++
using expected_type = expected;
auto f = [](value_type v) noexcept { return expected_type{ in_place, ++v}; };
expected_type ex{ in_place, value_type{2} };
auto res { std::move(ex).and_then(f) };
constexpr_test( std::same_as);
constexpr_test( res == value_type{3});
```
#### memutil::unaligned
```C++
consteval auto make_version_data(string_view sub_ver, string_view data_ver, uint16_t ver_minor, uint16_t comp_minor)
{
constexpr auto converter = [](char c) noexcept -> std::byte { return static_cast(c); };
std::array res{};
auto it{ranges::transform(sub_ver, res.begin(), converter).out};
*it = std::byte(' '); // make space
++it;
it = ranges::transform(data_ver, it, converter).out;
*it = std::byte{};
it = ranges::next(res.begin(), map_version_t::map_version_name_chars);
it = memutil::unaligned_store(it, expected_version_major);
it = memutil::unaligned_store(it, expected_version_minor);
it = memutil::unaligned_store(it, expected_version_major);
memutil::unaligned_store(it, expected_cmp_minor);
return res;
}
static constexpr std::array
polska_6_1451_6_18{ make_version_data("Polska", "2403", 1451, 18)};
```
#### shared mem utils
example using static vector, basic_static_string between processes with memory offset table declaration
```C++
//used types between processes
struct foo
{
int a,a_;
double b;
int64_t c;
};using message = coll::static_u8string<512>;
using vector_type = coll::static_vector;// memory offset table
using foo_obj_decl = ip::shared_type_decl;
using shared_vector_decl = ip::shared_type_decl;
using ref_obj_decl = ip::shared_type_decl;
using message_decl = ip::shared_type_decl;bip::mapped_region region ( shm, bip::read_write );
// construct objects in main process
foo & foo_obj{*ip::construct_at(region, foo{.a=1,.a_=0,.b=0.5, .c=0xffffffff })};
auto & ref_obj{*ip::construct_at(region, 2u)};
auto & ref_string { *ip::construct_at(region, u8"message hello world"sv) };
vector_type & vector_obj{ *ip::construct_at(region) };
resize(vector_obj,1);
front(vector_obj) = 2;//alter data at forked process
auto child = ip::fork([](std::string_view shared_mem_name )
{
bip::shared_memory_object shm_obj{ bip::open_only, shared_mem_name.data() , bip::read_write };
bip::mapped_region cregion{ shm_obj, bip::read_write };
//reference shared objects
foo & cfoo_obj{ ip::ref(cregion) };
vector_type & vector { ip::ref(cregion) };
auto & cref_string { ip::ref(cregion) };
auto & cref_obj{ip::ref(cregion)};//read write data
ut::expect( cfoo_obj.a == 1 );
ut::expect( cfoo_obj.b == 0.5 );
ut::expect( cfoo_obj.c == 0xffffffff );
cfoo_obj.a = 2;
cfoo_obj.b = 1.5;
cfoo_obj.c = -0x1ffffffff;
ut::expect(size(vector) == 1u );
ut::expect(front(vector) == 2u );
ut::expect(resize(vector,128) == coll::vector_outcome_e::no_error ) >> ut::fatal;
pop_back(vector);
std::iota(begin(vector), end(vector), 2);
ut::expect( cref_string.view() == u8"message hello world"sv );
cref_string = u8"hello world from child"sv;
cref_obj += 2;return true;
},
shmem_name );// check modified data at forked process
ut::expect(child->join()) >> ut::fatal;
ut::expect( foo_obj.a == 2 );
ut::expect( foo_obj.b == 1.5 );
ut::expect( foo_obj.c == -0x1ffffffff );ut::expect( ref_string.view() == u8"hello world from child"sv );
ut::expect(ref_obj == 4 );
ut::expect(size(vector_obj) == 127u );
ut::expect(front(vector_obj) == 2 );
ut::expect(back(vector_obj) == 128 );
```#### meta_packed_struct
```C++
enum struct mbs_fields
{
field_1, field_2, field_3, field_4
};
enum struct example_enum_value : uint8_t
{ value0 = 0, value1, value2, value3 };using enum mbs_fields;
// pack bit struct
using mixed_bitfiled_struct3 =
meta_packed_struct<
member,
member,
member,
member
>;
mixed_bitfiled_struct3 mbs;
get(mbs) = (0x1llu<<56)-1;
constexpr_test(get(mbs) == 0 );
constexpr_test(get(mbs) == false );
constexpr_test(get(mbs) == (0x1llu<<56)-1 );
constexpr_test(get(mbs) == example_enum_value{} );auto packed_value = pack_value(mbs);
constexpr_test(packed_value == 0b00'11111111111111111111111111111111111111111111111111111111'0'0000 );// unpack bitstruct
using mixed_bitfiled_struct2 =
meta_packed_struct<
member,
member,
member,
member
>;
constexpr auto fcount = filed_count();
constexpr_test(fcount == 4);
constexpr auto s_bit_width = bit_width();
constexpr_test(s_bit_width == 24);
uint32_t packed_value{ 0b011000011111111000010010 };
auto mbs{ unpack_value(packed_value) };constexpr_test(get(mbs) == 0x02 );
constexpr_test(get(mbs) == true );
constexpr_test(get(mbs) == 0x0ff0 );
constexpr_test(get(mbs) == value3 );
```
## Tested Compilers (as of v2.4.2)### Make Workflows Tested
- `cmake --workflow --preset="clang-18-libc++release"`
- `cmake --workflow --preset="clang-18-release"` using GNU libstdc++ on Linux
- `cmake --workflow --preset="gcc-14-release"`### MSVC
- Tested intermittently