So I'm trying to create a factory based on CRTP. For simplicity, I will just include whatever is relevant here. I got two questions which might be irrelevant to each other, but was stuck trying to find the keywords.
#include <bits/stdc++.h>
using namespace std;
static auto& GetFactoryMap() {
static vector<string> GLOBAL_FACTORY_MAP;
return GLOBAL_FACTORY_MAP;
}
template <typename Derived>
struct Registrar {
static int DoRegister() {
auto name = typeid(Derived).name();
GetFactoryMap().emplace_back(name);
return 1;
};
inline static const int _hello = DoRegister();
};
struct Foo : public Registrar<Foo> {};
int main() {
cout << GetFactoryMap().size();
}
Compiled with x86-64 clang-8.0.0, flag -std=c++17.
QUESTION 1: The program returned 0: https://godbolt.org/z/5c74TePT5. I expected it to print 1 as defining the class Foo should also define a Registrar<Foo>, which in turn will initialise the _hello and call DoRegister().
But when I do this:
int main() {
cout << Foo::_hello << endl;
cout << GetFactoryMap().size();
}
Then it did print 1 (the _hello) and 1 (the map size).
QUESTION 2: so I found out how to solve the first issue by dummy-calling _hello inside Registrar constructor.
template <typename Derived>
struct Registrar {
Registrar() {
(void)_hello;
}
...
}
But thing is, I still don't know WHY it can fix the issue. And even after I did that, the DoRegister seemed to only get called if I have an empty constructor OR a default constructor OUTSIDE the class definition, as seen by the global map size is only 2: https://godbolt.org/z/Me53q1x86.
What is happening here?
Implicit instantiation
TL;DR If it's not used, it's not instantiated.
Explicitly-defaulted functions
TL;DR
=defaultin the class only declares a thing; if it's not used it's not defined.