Static const map inside class/struct

I want a "global map" inside a class, which can be accessed from anywhere. Is it possible?


Something clean like this:

struct worker {

static const std::map<string, string> a = {

{"param", "light"}

};

};


Then: cout << worker::a["param"];



Best regards
Volang


Yes, I didn't try it, but that looks possible.
What errors are you getting?
error: in-class initialization of static data member 'const std::map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> > worker::a' of non-literal type
I think you want this.


struct worker
{
static const std::map<string, string> a;
};

const std::map<string, string> worker::a =
{ {"param", "light"} };


static class members have to be pushed out of the class this way, and I can't recall exactly why anymore.

not 100% sure but I think this forces you to use .at("param") instead of [] because [] does not respect const. But maybe someone else can speak on this.
Last edited on
Yep, I missed that. C# made me take that sort of thing for granted.

Yon can use the inline keyword to allow inline initialization, but this is a C++17 feature.

And jonnin you are correct, the [] discards const and can't be used, because [] adds to the map if the item doesn't exist. If you want to avoid exceptions, map.find must be used.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Example program
#include <iostream>
#include <string>
#include <map>

using std::cout;
using std::string;

struct worker {

  public:
    static const std::string& map(const std::string& str)
    {
        return a.at(str);
    }

  private:
    static const inline std::map<string, string> a = {  
        {"param", "light"}
    };

};


int main()
{
    cout << worker::map("param") << '\n';
}


Sadly, it appears that [] operator can only be used as a non-static class member, so no operator overloading :(
Last edited on
you can overload it normally if you want to access it from objects.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

struct worker 
{
 static const std::map<string, string> a;
 string  operator [](string s) {return a.at(s);}  
};

const std::map<string, string> worker::a = 
{ {"param", "light"} };


int main()
{
	  worker w;	  //you have to have an object to use [] 
	  cout << w["param"];
	  return 0;
}


I actually prefer to allocate the object, the cost is low and the syntax is nicer. Otherwise its just a global in a fancy namespace (using struct or class as a namespace surrogate)
Since it is constant, I would just namespace protect this in a const or constexp statement, same as you would do for any other constant, unless you have something else you want to do (like the operator, or some other method, ?) I code off the least thing needed ... which many will disagree with (eg Ill use an array if I don't need anything vector provides, or a free function if a class is not needed, etc). The downside of that is if you change your mind on what was needed, it may take a little work to fix.
Last edited on
Topic archived. No new replies allowed.