There is a need in my project for a registry that would hold some states and that could be easily accesible from anywhere in the code. Singleton is something we already use in a classic implementation static X& X::instance() { static X instance; return instance; } But this causes issues in UT. I came up with such a idea
smartSingletonWrapper.h
class smartSingletonWrapper
{
public:
smartSingletonWrapper(arg_for_Actual_Singleton)
{
instance.reset(make_shared<Actual_Singleton>(arg_for_Actual_Singleton));
}
~smartSingletonWrapper()
{
assert(instance.count() == 1, "In case you want sanity checks");
instace.reset();
}
static shared_ptr<Actual_Singleton> getInstance() //or weak_ptr
{
return instance;
}
private:
static shared_ptr<Actual_Singleton> instance;
class Actual_Singleton //or implement elsewhere with private constructor and wrapper as friend class
{
//stuff..
}
}
smartSingletonWrapper.cpp
shared_ptr<Actual_Singleton> smartSingletonWrapper::instance;
Now usage of this would be:
int main(argc, argv)
{
smartSingletonWrapper raii_singleton_holder;
invoke_milions_lines_of_code();
return 0;
}
in UT well same story just create this object anywhere where it will run out of scope after 1 test is over. Example basing on gtest:
class ut_class_using_actual_singleton : public testing::Test
{
public:
class_using_actual_singleton system_under_test;
smartSingletonWrapper
};
TEST_F(ut_class_using_actual_singleton, some_test)
{
test_stuff();
}
This is simple yet working version. You can enhance it by making this class a template accepting just any kind of singleton class inside it. You can add sanity checks (for example checking if there is only one instance of this smartSingleton).
Does anyone see any issues with this idea? Have anyone heard of similar idea? I don't believe that I actually invented something no-one has ever described before.