(I know) In c++ I can declare variable
out of scope and I can't run any code/statement, except for initializing global/static variables.
IDEA
Is it a good idea to use below tricky code in order to (for example) do some std::map
manipulation ?
Here I use void *fakeVar
and initialize it through Fake::initializer()
and do whatever I want in it !
std::map<std::string, int> myMap;
class Fake
{
public:
static void* initializer()
{
myMap["test"]=222;
// Do whatever with your global Variables
return NULL;
}
};
// myMap["Error"] = 111; => Error
// Fake::initializer(); => Error
void *fakeVar = Fake::initializer(); //=> OK
void main()
{
std::cout<<"Map size: " << myMap.size() << std::endl; // Show myMap has initialized correctly :)
}
§ 8.5.2 states
therefore what you're doing is perfectly allowed by the C++ standard. That said, if you need to perform "initialization operations" it might be better to just use a class constructor (e.g. a wrapper).
When I hear "tricky code", I immediately think of code smells and maintenance nightmares. To answer your question, no, it isn't a good idea. While it is valid C++ code, it is bad practice. There are other, much more explicit and meaningful alternatives to this problem. To elaborate, the fact that your initializer() method returns void* NULL is meaningless as far as the intention of your program goes (i.e. each line of your code should have meaningful purpose), and you now have yet another unnecessary global variable fakeVar, which needlessly points to NULL.
Let's consider some less "tricky" alternatives:
If it's extremely important that you only ever have one global instance of myMap, perhaps using the Singleton Pattern would be more fitting, and you would be able to lazily initialize the contents of myMap when they are needed. Keep in mind that the Singleton Pattern has issues of its own.
Have a static method create and return the map or use a global namespace. For example, something along the lines of this:
If this is a map with specialized functionality, create your own class (best option)! While this isn't a complete example, you get the idea:
No.
Any solution entailing mutable non-local variables is a terrible idea.
This answer is similar to Some programmer dude's answer, but may be considered a bit cleaner. As of C++17 (that's when
std::invoke()
was added), you could do something like this:In C++, you cannot have statements outside any function. However, you have global objects declared, and constructor (initializer) call for these global objects are automatic before main starts. In your example, fakeVar is a global pointer that gets initialized through a function of class static scope, this is absolutely fine.
Even a global object would do provide that global object constructor does the desired initializaton. For example,
This is a case where unity builds (single translation unit builds) can be very powerful. The
__COUNTER__
macro is a de facto standard among C and C++ compilers, and with it you can write arbitrary imperative code at global scope:This is especially powerful once you realize that you can use it to initialize static variables without a dependency on the C runtime. This means you can generate very small executables without having to eschew non-zero global variables: