/flat

Flat containers for C++

Primary LanguageC++Boost Software License 1.0BSL-1.0

C++ Flat Containers Library

Fast+efficient associative containers using sorted arrays, with an interface based on standard containers.

This was part of a C++ standard proposal and I recommend that you read it for more details: http://pubby.github.io/proposal.html

Container Adaptors

  • fc::flat_map
  • fc::flat_multimap
  • fc::flat_set
  • fc::flat_multiset

Class Aliases

  • fc::vector_map
  • fc::vector_multimap
  • fc::vector_set
  • fc::vector_multiset

Differences from Standard Containrs

  • Due to using vectors internally, map's value_type is std::pair<K, V> instead of std::pair<const K, V>, and all iterators are const_iterators, by default. It's still possible to modify the stored values though - see below.
  • Flat containers have O(log(n)) find complexity, but O(n log(n)) insertion and deletion. They're ideal for when one doesn't need to store very much data, or for when one performs finds far more often than insertions.

New Member Functions

  • has
    • map.has(key) returns a pointer to key's mapped value if it exists, otherwise returns null.
  • insert (delayed sort)
    • map.insert(first, last, fc::delay_sort) performs insertion with a delayed sort optimization.
  • Constructors (delayed sort overload)
    • Constructs flat container using a delayed sort optimization.
  • Constructors (container construct overload)
    • Constructs flat container by forwarding arguments to the underlying container member.

What's an adaptor?

Container adaptors allow you to use any vector-like sequence container for the underlying storage. std::vector is the natural choice, but classes like boost::small_vector and boost::static_vector are useful too. Because std::vector is the most common in usage, aliases are provided for convenience.

For basic use, just use the std::vector aliases.

The public Members: container and underlying

The public member container allows access to the underlying storage container. Note that it is the user's responsibility to keep the container in a sorted, unique state.

Likewise, the public member of iterators: underlying, allows access to the underlying storage container's iterators.

Example: Delayed sort optimization using .container

std::flat_multiset<int> set;
while(cpu_temperature() < 100)
    set.container.push_back(cpu_temperature());
std::sort(set.begin(), set.end());

Const Iteration by Default

For safety reasons, flat container iterators are const by default. To bypass this safety and get non-const iterators, one can either iterate .container or take the .underlying of the iterator.

Example: Modify values in a way that preserves sortedness

for(auto& v : set.container)
    v *= 2;

Example: Same thing but with .underlying

for(auto it = v.begin(); it != v.end(); ++it)
    (*v.underlying) *= 2;

For maps, one can also use .has and .operator[]:

Example: using .has and .operator[]

map["foo"] = "bar";

if(std::string* value = map.has("qux"))
    *value = "baz";

Helper Types

The directory include_extra contains convenience typedefs for use with Boost.Container. These typedefs make it trivial to use flat containers that use stack-based allocation instead of the heap.