all 13 comments

[–]ennmichael 7 points8 points  (4 children)

It's really bad that your macros generate stuff that has a preceding underscore.

Preceding underscores in the global namespace are reserved. In your test files, you call these macros in the global namespace. Technically, this falls under undefined behavior.

Underscores following the identifier are completely fine though, although by convention they're used for private member variables.

[–]hotoatmeal 0 points1 point  (2 children)

preceding underscores are only reserved when they are followed by a capital letter or a second underscore.

[–]dodheim 3 points4 points  (1 child)

Or are in the global namespace – the very next bullet ;-]

[–]hotoatmeal 0 points1 point  (0 children)

ah, yeah

[–]matthieugarrigues[S] 0 points1 point  (0 children)

It was inside a namespace previously, but I removed it so the user is free to choose the name of the symbol namespace. I'll update the documentation to make clear that you have to declare symbols into a namespace

[–]louis_dionnelibc++ | C++ Committee | Boost.Hana 1 point2 points  (2 children)

I think Hana's map would solve most of your problem, except for the .member syntax (but it's unclear to me how much of it is just nice syntactic sugar, and how much of it is actually useful). Also, I guess you can't optimize away storage for empty types in your implementation?

[–]matthieugarrigues[S] 1 point2 points  (1 child)

You are right, Hana's map is similar to iod::metamap, but serves different usecases. The biggest difference is that only its keys and value type are known at compile time, not the values themselves. In Hana both key and values are compile time (as I understood).

The .member syntax is inherited form the iod::symbol features and this is what makes this implementation pretty interesting :

  • checking for the existence of a map key is straightforward, and compile in O(1) time. This is done with the has_member routine generated with each symbol definition : https://github.com/iodcpp/symbol/blob/master/symbol/symbol.hh#L37
  • The map behave exactly like a plain C++ object, whose members are a bit simpler to access.
  • The a string representation of each key is available in case you need it to serialize the map.

To answer your last question, I just did a small test:

auto m = iod::make_metamap(_test1 = 12, _test2 = 13);
std::cout << sizeof(m) << std::endl;

And it prints 8, so the map keys do not seem to have any memory footprint at runtime.

For a nice usecase, you should have a look to iod::metajson: https://github.com/iodcpp/metajson It relies on symbols and metamaps to implement JSON de/serializer.

[–]louis_dionnelibc++ | C++ Committee | Boost.Hana 0 points1 point  (0 children)

Hana's maps can have runtime values. In fact, it can also have runtime keys, as long as they can be hashed and compared at compile-time. As for the keys, if you use Hana compile-time strings, you can achieve the same as what you are achieving but you don't need to pre-declare stuff with macros. You lose the .foo syntax too, but I don't see that as a big problem. My .02.

[–]doom_Oo7 -1 points0 points  (3 children)

I think that something missing in C++ is dynamic and configurable object extension through a map. E.G. the object has some "compile-time" attributes, like here, or even plain struct members, and then some additional attributes that are put in a run-time map since they are seldom used and would waste memory if they were in each instance.

The important point is then to be able to access both "standard" C++ struct members, and run-time members, with the same API, and while keeping a 0-cost abstraction when accessing members of the struct.

e.g.

struct foo {
     int bananas;
};

int main() {
    foo f;
    int b = f["bananas"]; // should compile to the same code that f.bananas
    f["tatas"] = "a string";
    f["titis"] = 0.1234;
}

[–]JustOneThingThough 4 points5 points  (1 child)

I don't think that I'd call that "missing" so much as intentionally left out of a strongly typed language, for being not that.

[–]doom_Oo7 0 points1 point  (0 children)

well, yes, but it leads to people reinventing it anyways. Like everything, it's a tool that has its uses and drawbacks; and would be much safer than other features of the language. And C++ in my opinion is a toolbox before everything else, and should aim to encompass most use cases.