serge-sans-paille / frozen

a header-only, constexpr alternative to gperf for C++14 users
Apache License 2.0
1.27k stars 103 forks source link

How to create a string key at runtime? #143

Open jgm-ktg opened 2 years ago

jgm-ktg commented 2 years ago

Here is non-frozen code. I need the key being looked up to come from data outside the program... i.e. not a literal. Does frozen do this or does it not solve that gperf-like problem?

        std::unordered_map<std::string_view, int> m = {
                        {{"even_length",11},0},
                        {{"length",6},1},
                        {{"maybe",5},2},
                        {{"symbol",6},3},
                        {{"space_to_nonspace",17},4}
                        };
        std::string line;
        std::getline(std::cin, line);
        fprintf(stderr,"%s\n", line.c_str());

        fprintf(stderr,"%.*s index: %d\n", (int)line.length(), line.c_str(), m.at({line.c_str(),line.length()}));
serge-sans-paille commented 2 years ago

Sure, it works as expected:

  constexpr frozen::unordered_map<frozen::string, int, 5> m = {
      {{"even_length", 11}, 0},
      {{"length", 6}, 1},
      {{"maybe", 5}, 2},
      {{"symbol", 6}, 3},
      {{"space_to_nonspace", 17}, 4}};
  std::string line;     
  std::getline(std::cin, line);
  fprintf(stderr, "%s\n", line.c_str());

  fprintf(stderr, "%.*s index: %d\n", (int)line.length(), line.c_str(),
          m.at(frozen::string(line.c_str(), line.size())));
jgm-ktg commented 2 years ago

Thank you! For some reason I could not find an example of constructing a string key at runtime. frozen::string(line.c_str(), line.size()) is a very lightweight/efficient operation, correct? Specifically, it does not allocate/free on the heap or copy the string data, correct?

ljleb commented 1 year ago

@jgm-ktg look at frozen::string's constructor: it merely copies the arguments themselves into the object, so no deep copy or anything of the sort at the moment (and I assume changing this behavior could break existing code that uses frozen).

bazineta commented 12 months ago

Related question, since I've stumbled upon this after failing to get heterogeneous lookup working for this case in frozen::map. That is, this is the thing that heterogeneous lookup was designed for, and I see in the test cases that there are tests for that, but not for strings, and my entreaties to the compiler with respect to use of std::less<> and the usual ordering comparison functions have only resulted in puzzling template error spew, so I'm curious if I'm just missing something obvious here.

bazineta commented 12 months ago

Answering my own question; the reasons I was even interested in heterogeneous lookup in the first place are obviated by #158, so it's moot once that lands. That is, a find() against the unordered_map in the original posting, using a std::string argument, will Just Work™ at that point. Specifically, this bit here:

Specifically this uses `FROZEN_LETITGO_HAS_STRING_VIEW`. Not
`#include`ing `defines.h` ourselves results in an include-ordering
dependency.

Obvious now that I see it, but, well, thanks @muggenhor, couldn't for the life of me find that, and it was making me crazy.