Hacker News new | ask | show | jobs
by hogliux 2790 days ago
Yes, in a way you are right: the compiler really does boil it down to global variables. However, `semi::static_map` gives you some additional features, which may be useful for a lot of situations

1) `semi::static_map` gives you the optional run-time look-up with the same API (`semi::static_map::get`). Looking up a global variable with a runtime key isn't straight-forward. This makes it particularly nice to use an API where a function might take either a compile-time or run-time key. I'm thinking a Font API with a `getFont` method, for example. The way you use the method is the same regardless if you are using a compile-time key or not.

2) `semi::static_map` also gives you control over the lifetime of the objects. For example, it's easy to delete all the values in the map at once. Again, this is not straight-forward to do with a bunch of globals.

3) the keys are also values themselves and it's straight-forward to evaluate them at run-time. Printing the name of a global variable, for example, requires all sorts of hackery.

4) you do not need to know all your keys in advance. Simply using getFont with a unique constexpr key will create a new global variable.

Edit: added point (4)

2 comments

Re: 3), here's a clean and technically humble way that I typically use.

    enum {
        KEY_FOO,
        KEY_BAR,
        KEY_BLAH,
        NUM_KEYS,
    };

    struct KeyInfo {
        const char *name;
        int info1;
        float info2;
    };

    const static struct KeyInfo keyInfo[NUM_KEYS] = {
    #define MAKE(x, y, z) [x] = { #x, y, z }
        MAKE( KEY_FOO,   1,   1.0 ),
        MAKE( KEY_BAR,   7,   3.5 ),
        MAKE( KEY_BLAH, 42, 127.2 ),
    #undef MAKE
    };

    void print_key(int key)
    {
        printf("%d's name is %s\n", key, keyInfo[key].name);
    }
It's both low-tech and maintainable. It compiles super quick. If one doesn't like that one has to type KEY_FOO twice (in the enum and in the array definition), one can use X-macros or code generation. But personally I don't care.
Yes, that's a nice approach. However, this approach requires you to list all your keys in advance (in the enum).

The `semi::static_map` does not require this.This is especially useful if you are writing library code: imagine you are programming a `getFont` method - you don't know with which constexpr keys your method will be called, so there is no way for you to list all these keys in an enum.

If you don't like pointlessly repeating occurrences of identifiers, you should hardly be favoring C++.

   class foo {
   public:
     foo();
     ~foo();
   };
 
   foo::foo() { }

   foo::~foo() { }
Ad nauseum.

Oh, but C++ can eliminate redundancy in this one cool case I'm thinking of!

C++ doesn't support designated initialisers.
Thanks for this clarification! I agree it can be useful.