How can one emulate a constructor for a class template with static members only and force specializations of the constructor?
I want to achieve an emulated "static constructor" but with class templates and without un-specialized constructor (function template). These functions must be implicitly called (although it must be handled with care) and a separate function must be defined for each class template instantiation.
Also I want to separate the (1) definition of the class (and everything else necessary for the constructor emulation) from the (2) template instantiation and specialized "constructor" definition. The (1) part should have no dependency to the (2).
The operations by the "constructor" may only effect global static memory.
Attempt 1 "ripped"
Here is what I have so far:
#include <iostream>
using namespace std;
// -------------------- BEGIN PART (1)
template<int N> struct S
{
struct IS { };
static IS init();
static IS is;
static void foo() { cout << "foo called by S<" << N << ">" << endl; }
};
// -------------------- END PART (1)
// -------------------- BEGIN PART (2)
template<> S<1>::IS S<1>::init() // "constructor" specialized for "1"
{
cout << "init called by S<1>" << endl;
// do stuff specific to "1"
return {};
}
template<> S<3>::IS S<3>::init() // "constructor" specialized for "3"
{
cout << "init called by S<3>" << endl;
// do stuff specific to "3"
return {};
}
// -------------------- END PART (2)
// -------------------- BEGIN PART (1)
template<> S<1>::IS S<1>::is = init();
// -------------------- END PART (1)
int main()
{
cout << "Hello, Wandbox!" << endl;
S<3>::foo();
}
Output:
init called by S<1>
Hello, Wandbox!
foo called by S<3>
In this case I need an error from the compiler / linker that tells the programmer that S<3>::is
is undefined. The point is to make sure the initialization has not been forgotten by mistake.
Attempt 2 "order problem"
Here the class definition and the usage specific are separated as desired. But it can not compile.
structure.hpp
template<int N> struct S
{
struct IS { };
static IS init();
static IS is;
};
template<> S<1>::IS S<1>::is = init();
template<> S<2>::IS S<2>::is = init();
main.cpp
#include <iostream>
#include "structure.hpp"
using namespace std;
template<> S<1>::IS S<1>::init() // "constructor" specialized for "1"
{
cout << "init called by S<1>" << endl;
// do stuff specific to "1"
return {};
}
template<> S<3>::IS S<3>::init() // "constructor" specialized for "3"
{
cout << "init called by S<3>" << endl;
// do stuff specific to "3"
return {};
}
int main()
{
cout << "Hello, Wandbox!" << endl;
}
Compilation error:
error: specialization of 'static S<N>::IS S<N>::init() [with int N = 1]' after instantiation
5 | template<> S<1>::IS S<1>::init() // "constructor" specialized for "1"
| ^