Use C ++ 11 constexpr to initialize std :: map

I want to initialize std :: map with the keys being constexpr. Consider the following C ++ 11 MWE:

#include <map>
using std::map;

constexpr unsigned int str2int(const char* str, const int h = 0) {
    return !str[h] ? 5381 : (str2int(str, h + 1) * 33) ^ str[h];
}

const map<unsigned int, const char*> values = {
    {str2int("foo"), "bar"},
    {str2int("hello"), "world"}
};

int main() { return 0; }

While the code compiles the latest clang and gcc, the resulting binary will contain key type strings:

C String Literals

Why are keys contained in a binary file, even if they are used as constexpr? Is there any way around this behavior?

Of course, map initialization will occur at run time. But shouldn't the binary values ​​be replaced with constexpr at compile time?

Note. This, of course, is a simplified example. I know that there are various gain structures that may be more suitable for this use case. I am particularly interested in why this is happening.

[]

, . , bar :

#include <map>
#include <iostream>
#include <string>

using namespace std;

constexpr unsigned int str2int(const char* str, const int h = 0) {
  return !str[h] ? 5381 : (str2int(str, h + 1) * 33) ^ str[h];
}

int main() {
  string input;
  while(true) {
    cin >> input;
    switch(str2int(input.c_str())) {
      case str2int("quit"):
      return 0;
      case str2int("foo"):
      cout << "bar" << endl;
    }
  }
}

$ for x in "gcc-mp-7" "clang"; do 
  $x --version|head -n 1
  $x -lstdc++ -std=c++11 -Ofast constexpr.cpp -o a
  $x -lstdc++ -std=c++1z -Ofast constexpr.cpp -o b
  strings a|grep hello|wc -l
  strings b|grep hello|wc -l
done

gcc-mp-7 (MacPorts gcc7 7.2.0_0) 7.2.0
       1
       0
Apple LLVM version 8.1.0 (clang-802.0.38)
       1
       0
+6
4

g++ (trunk), clang++ (trunk). : -std=c++1z -Ofast. strings: "foo" "hello".

?

, str2int . , :

constexpr auto k0 = str2int("foo");
constexpr auto k1 = str2int("hello");

const map<unsigned int, const char*> values = {
    {k0, "bar"},
    {k1, "world"}
};
+1

--std=c++11 -O2 GCC 7.2, clang 5.0 MSVC 17.

DEMO

(-g)? , .

+1
template<unsigned int x>
using kuint_t = std::integral_constant<unsigned int, x>;

const map<unsigned int, const char*> values = {
  {kuint_t<str2int("foo")>::value, "bar"},
  {kuint_t<str2int("hello")>::value, "world"}
};

.

:

template<unsigned int x>
using kuint_t = std::integral_constant<unsigned int, x>;
template<unsigned int x>
kuint_t<x> kuint{};

const map<unsigned int, const char*> values = {
  {kuint<str2int("foo")>, "bar"},
  {kuint<str2int("hello")>, "world"}
};

:

template<auto x>
using k_t = std::integral_constant<std::decay_t<decltype(x)>, x>;
template<auto x>
k_t<x> k{};

const map<unsigned int, const char*> values = {
  {k<str2int("foo")>, "bar"},
  {k<str2int("hello")>, "world"}
};

.

0

const . , :

const map<unsigned int, const char*> values

const, constexpr. str2int , . const , , .

, Serge Sans Paille Frozen constexpr - https://github.com/serge-sans-paille/frozen

, ++ 11, , .

, - - O (1) ( ).

gperf.

Clang GCC , . 2048 1G RAM VPS Clang. GCC .

0

Source: https://habr.com/ru/post/1689153/


All Articles