#include <iostream>
#include <string>
#include <stdexcept>
//Some made up configuration data for a Foo class.
struct FooConfig
{
int i;
double d;
};
//Some made up configuration data for a Bar class.
struct BarConfig
{
int x;
double y;
};
//Configurations can be shared among classes.
struct SharedConfig
{
std::string text;
};
//The actual wrapper.
template <class T>
class StaticConfig
{
public:
StaticConfig()
{
if (!mIsInitialised)
{
throw std::runtime_error("Tried to construct uninitialised StaticConfig!");
}
}
const T*
operator -> () const
{
return &mConfig;
}
private:
friend class ConfigHandler;
StaticConfig(const T& config)
{
mConfig = config;
mIsInitialised = true;
}
static T mConfig;
static bool mIsInitialised;
};
template <class T>
T StaticConfig<T>::mConfig;
template <class T>
bool StaticConfig<T>::mIsInitialised = false;
//ConfigHandler responsible for loading the data.
class ConfigHandler
{
public:
ConfigHandler() :
mFooConfig(GetFooConfig()),
mBarConfig(GetBarConfig()),
mSharedConfig(GetSharedConfig())
{}
FooConfig
GetFooConfig()
{
FooConfig fooConfig;
fooConfig.i = 1337;
fooConfig.d = 123.45;
return fooConfig;
}
BarConfig
GetBarConfig()
{
BarConfig barConfig;
barConfig.x = 69;
barConfig.y = 987.65;
return barConfig;
}
SharedConfig
GetSharedConfig()
{
SharedConfig sharedConfig;
sharedConfig.text = "This is a std::string!";
return sharedConfig;
}
private:
StaticConfig<FooConfig> mFooConfig;
StaticConfig<BarConfig> mBarConfig;
StaticConfig<SharedConfig> mSharedConfig;
};
class Foo
{
public:
void
Print()
{
std::cout << "Foo prints " << mConfig->i << " " << mConfig->d << " "
<< mSharedConfig->text << '\n';
}
private:
StaticConfig<FooConfig> mConfig;
StaticConfig<SharedConfig> mSharedConfig;
};
class Bar
{
public:
void
Print()
{
std::cout << "Bar prints " << mConfig->x << " " << mConfig->y << " "
<< mSharedConfig->text << '\n';
}
private:
StaticConfig<BarConfig> mConfig;
StaticConfig<SharedConfig> mSharedConfig;
};
int main()
{
//If uncommented, this next line throws as it attempts to...
//...construct a StaticConfig<FooConfig> inside foo before...
//...ConfigHandler has a chance to initialise things.
//Foo aFoo;
//ConfigHandler must only briefly exist to load data.
ConfigHandler();
Foo foo;
Bar bar;
foo.Print();
bar.Print();
return 0;
}