TheMaverickProgrammer / varvec

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Variable Vectors

Build Status Coverage Status

The idea behind this repository is to implement a set of "variable vector" types, built on top of std::variant machinery (although extensible to any type that implements the same API), allowing a user to store heterogenous types in a std::vector-like container, but while also maintaining a minimal memory footprint by contiguously packing data as tightly as possible.

For trivial types, the data is stored in a packed format that completely ignores alignment requirements (data is re-aligned on-demand during access), and for non-trivial user defined types, the data is stored on native alignment boundaries, but each entry only needs the storage required by the current type, not the common size of all types as would be the case with std::vector<std::variant<...>>.

Basic Usage

The library customizes into many different types, but at a high level there are only three types exported, a vector implementation, an iterator, and an overload helper for composing lambdas (still waiting on a standard option).

A motivating example akin to std::vector<std::variant<...>>:

#include <varvec.hpp>

int main() {
    // A complex vector type.
    using mixed_vector = varvec::static_vector<
        32,   // Total space to use for member storage
        5,    // Max members
        bool, // Types...
        int,
        float,
        double,
        std::unique_ptr<std::string>
    >;

    // Fill it with data of all types.
    mixed_vector vals;
    vals.push_back(true);
    vals.push_back(42);
    vals.push_back(0.5f);
    vals.push_back(3.14159);
    vals.push_back(std::make_unique<std::string>("hello world"));

    // Outputs:
    // Using visit_at syntax: 0.5
    // Using get_at syntax: hello world
    vals.visit_at(2, [] (auto& v) {
        std::cout << "Using visit_at syntax: " << v << std::endl;
    });
    std::cout
        << "Using get_at syntax: "
        << *vals.get_at<std::unique_ptr<std::string>>(4)
        << std::endl;

    // Outputs:
    // Range for: 1
    // Range for: 42
    // Range for: 0.5
    // Range for: 3.14159
    // Range for: hello world
    for (mixed_vector::value_type variant : vals) {
        std::visit(varvec::overload {
            [] <class T> (T* ptr) { std::cout << "Range for: " << **ptr << std::endl; },
            [] (auto& val) { std::cout << "Range for: " << val << std::endl; }
        }, variant);
    }

    // Outputs:
    // 39
    // std::vector<variant<...>> would require ~80 bytes.
    std::cout << vals.used_bytes() << std::endl;
}

About


Languages

Language:C++ 98.9%Language:CMake 1.1%