Coder Social home page Coder Social logo

skyformat99 / semimap Goto Github PK

View Code? Open in Web Editor NEW

This project forked from hogliux/semimap

0.0 1.0 0.0 24 KB

A semi compile-/run-time associative map container with compile-time lookup and run-time storage

Home Page: https://www.youtube.com/watch?v=qNAbGpV1ZkU

License: MIT License

CMake 1.01% C++ 98.99%

semimap's Introduction

semi::static_map and semi::map

This container was the topic of a cppcon talk:

https://www.youtube.com/watch?v=qNAbGpV1ZkU

(slides: https://goo.gl/igwVxD )

associative map containers with compile-time lookup!

Normally, associative containers require some runtime overhead when looking up their values from a key. However, when the key is known at compile-time (for example, when the key is a literal) then this run-time lookup could technically be avoided. This is exactly what the goal of semi::static_map and semi::map is.

In fact, when using semi::static_map and looking up a value with C++ literal as a key, then the value lookup is nearly as efficient as looking up a global variable (on x86/arm it will reduce to only three machine instructions: a cmp, jne and a direct load). As long as you use C++ literals as your keys, the computational time of the lookup will stay constant and, for example, will not increase with the number of keys in your container!

#include <iostream>
#include <string>

#include "semimap.h"

#define ID(x) []() constexpr { return x; }

int main()
{
  semi::map<std::string, std::string> map;

  // Using string literals to access the container is super fast:
  // computational complexity remains constant regardless of the number of key, value pairs!
  map.get(ID("food"))  = "pizza";
  map.get(ID("drink")) = "soda";
  std::cout << map.get(ID("drink")) << std::endl;


  // Values can also be looked-up with run-time keys
  // which will then use std::unordered_map as a fallback.
  std::string key;

  std::cin >> key;
  std::cout << map.get(key) << std::endl; // for example: outputs "soda" if key is "drink"

  // there is also a static version of the map where lookeup is even faster
  struct Tag {};
  using Map = semi::static_map<std::string, std::string, Tag>;

  // in fact, it is (nearly) as fast as looking up any plain old global variable
  Map::get(ID("food")) = "pizza";
  Map::get(ID("drink")) = "beer";
  
  return 0;
}

The containers are very simple and only have the methods get, erase, contains and clear. get can also take any number of extra optoinal parameters which will be passed to your value's constructor if the value is not already in the container. As such, get is very similar to std::map's try_emplace. For example:

#define ID(x) []() constexpr { return x; }

semi::map<std::string, std::string> m;

m.get(ID("food"), "pizza");      // a value with key food is not already in the map so construct it with the parameter "pizza"
m.get(ID("food"), "spaghetti");  // a value with key food is in the map. The second parameter will not be used

There are two variants of the map:

  1. semi::map behaves very similar to a normal associative container. It's methods are non-static, so that the key, value pairs are not shared between several instances of semi::maps (as one would expect).
  2. semi::static_map is completely static. It's even faster than semi::map. However, to achieve this speed, it requires that all the methods are static. This means that two semi::static_maps, with same key and value types, will share their contents. To avoid this, there is a third optional "tag" template parameter. Only semi::static_maps that also have the same tag template type will share their contents. It's useful to use a local struct as the tag type, like follows:
void foo()
{
  struct Tag {};
  using map = semi::static_map<std::string, int, Tag>;

  map::get(ID("age")) = 18;
}

As this ensures that even if the same struct name "Tag" is used in another block, the semi::static_maps will not share their contents.

Also note, that as a static type, the contents of the semi::static_map will only be deleted when the program is exited. If you need to delete your key/values sooner then use the clear method.

-Fabian

@hogliux

semimap's People

Contributors

bsergeev avatar hogliux avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.