We have a rather large project that defines static const std::strings in several places to be used as parameter names; some of them need to be concatenated during static initialization:
foo.h:
struct Foo {
static const std::string ParamSuffix;
};
foo.cpp:
const std::string Foo::ParamSuffix = ".suffix";
bar.h:
struct Bar {
static const std::string ParamPrefix;
};
bar.cpp:
const std::string Bar::ParamPrefix = "prefix";
baz.h:
struct Baz {
static const std::string ParamName;
};
baz.cpp:
const std::string Baz::ParamName = Bar::ParamPrefix + Foo::ParamSuffix;
The problem is obviously the "static initialization fiasco" as it is undefined in which order the static const members are initialized.
I dislike the usual solution, i.e. replace all these variables by functions, because
- There's a lot of these variables, i.e. a lot of code changes
- The concatenations require special functions, which makes the code base inconsistent and even more ugly
I currently cannot use C++11, which would make things easier with its constexpr feature (I think).
The question is: Is there any trick that would allow me to concatenate static const std::strings (or wrapper objects or whatever) to initialize another static const std::string?
Why do you think that
std::string constis in any way special? (hint: it is not) Even if you could use C++11'sconstexprit wouldn't help because you can't makestd:strings constant expressions (they may need to allocate memory which isn't a viable constant expression). You could deal with a string-like class used forconstexprthat could be made to convert tostd::stringbut I'm not sure if these could be concatenated to produce a newconstexpr.What you maybe able to do is to extract those strings you need to use as part of a concatenation and provide their value as macro. String literals (which have type
char const[N]for a suitableN) can be concatenated by simply placing them next to each other:I would guess that
BAZ_PARAM_NAMEisn't used elsewhere in which case it also doesn't have to be defined: it is defined just to show it can be done. The initialization ofBar::ParamNameassumes thatBAZ_PARAM_NAMEisn't defined.