Reputation: 852
We have classes which have exposed the static data member as public members like
class A{
public:
static const string NAME;
//Other class specific methods
};
And similarly class B and few other classes.
If I have to create a map something like
static const map<string, string> versionMap = {{A().NAME, "Aa"},
{B().NAME, "Bb"}
};
Temporary objects of classes being created while creating the versionMap, is it guaranteed to have defined behavior all the time?
Upvotes: 2
Views: 404
Reputation: 114481
It is guaranteed to work only if
A.cpp
)You're however playing with fire... instead of depending on the static initialization order it's probably better to use a local static variable defined inside a static member function; i.e.
// File A.h
struct A {
static const std::string& NAME();
};
// File Map.cpp
std::map<std::string, std::string> x{{A::NAME(), "A"}};
// File A.cpp
static const std::string& A::NAME() {
static std::string x = "A string";
return x;
}
This approach is guaranteed to work because local static variables are initialized at the first use (and even automatically protected for multithreading issues in C++11).
Upvotes: 1
Reputation: 131546
It seems like you might be implementing some sort of reflection mechanism, with class names. Why not actually get class names, as names?
Have a look at:
Can I obtain C++ type names in a constexpr way?
the accepted answer there allows you to write get_name<A>()
and get a string(_view) which is "A". And get_name<B>()
will be "B" and so on. This is might be useful in your case, since:
Upvotes: 1
Reputation: 943
When you define a static member of a class, regardless of whether or not that class is instantiated, that member is accessible through memory. In this case, since they're public members, using the strings themselves as keys is perfectly valid.
That said, your static constant members need to be initialized after the class definition, typically something like:
class Foo { static const int foo; };
const int Foo::foo = 42;
For your static map example, you need to keep in mind that the map must be initialized similarly if used as a class member. Here's a working example:
// Compiled with g++ --std=c++17 -Wall -Wextra -Werror ConstStaticMapExample.cpp -o ConstStaticMapExample
#include <iostream>
#include <string>
#include <map>
class A
{
public:
static const std::string NAME;
//Other class specific methods
};
const std::string A::NAME = "foo";
class B
{
public:
static const std::string NAME;
//Other class specific methods
};
const std::string B::NAME = "bar";
class C
{
public:
static const std::map<std::string, std::string> versionMap;
// More definitions
};
const std::map<std::string, std::string> C::versionMap = {{A::NAME,"aA"},{B::NAME,"bB"}}; // Reversed for explanation
int main(int,char**)
{
// local static
static const std::map<std::string, std::string> versionMap = {{A::NAME,"Aa"},{B::NAME,"Bb"}};
std::cout << "LOCAL STATIC EXAMPLE:" << std::endl;
for(auto mpair : versionMap)
{
std::cout << "Key: " << mpair.first << "\tVal: " << mpair.second << std::endl;
}
// class member static
std::cout << "CLASS MEMBER STATIC EXAMPLE:" << std::endl;
for(auto mpair : C::versionMap)
{
std::cout << "Key: " << mpair.first << "\tVal: " << mpair.second << std::endl;
}
return 0;
}
Upvotes: 0