Releasing class members used in different synchronization contexts - c++

I am learning about the singleton design pattern with Chapter 29 of Professional C++, Second Edition1.
It illustrates a singleton implementation of a Logger class that covers thread-safety requirements:
Header
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <mutex>
// Definition of a multithread safe singleton logger class
class Logger
{
public:
static const std::string kLogLevelDebug;
static const std::string kLogLevelInfo;
static const std::string kLogLevelError;
// Returns a reference to the singleton Logger object
static Logger& instance();
// Logs a single message at the given log level
void log(const std::string& inMessage,
const std::string& inLogLevel);
// Logs a vector of messages at the given log level
void log(const std::vector<std::string>& inMessages,
const std::string& inLogLevel);
protected:
// Static variable for the one-and-only instance
static Logger* pInstance;
// Constant for the filename
static const char* const kLogFileName;
// Data member for the output stream
std::ofstream mOutputStream;
// Embedded class to make sure the single Logger
// instance gets deleted on program shutdown.
friend class Cleanup;
class Cleanup
{
public:
~Cleanup();
};
// Logs message. The thread should own a lock on sMutex
// before calling this function.
void logHelper(const std::string& inMessage,
const std::string& inLogLevel);
private:
Logger();
virtual ~Logger();
Logger(const Logger&);
Logger& operator=(const Logger&);
static std::mutex sMutex;
};
Implementation
#include <stdexcept>
#include "Logger.h"
using namespace std;
const string Logger::kLogLevelDebug = "DEBUG";
const string Logger::kLogLevelInfo = "INFO";
const string Logger::kLogLevelError = "ERROR";
const char* const Logger::kLogFileName = "log.out";
Logger* Logger::pInstance = nullptr;
mutex Logger::sMutex;
Logger& Logger::instance()
{
static Cleanup cleanup;
lock_guard<mutex> guard(sMutex);
if (pInstance == nullptr)
pInstance = new Logger();
return *pInstance;
}
Logger::Cleanup::~Cleanup()
{
lock_guard<mutex> guard(Logger::sMutex);
delete Logger::pInstance;
Logger::pInstance = nullptr;
}
Logger::~Logger()
{
mOutputStream.close();
}
Logger::Logger()
{
mOutputStream.open(kLogFileName, ios_base::app);
if (!mOutputStream.good()) {
throw runtime_error("Unable to initialize the Logger!");
}
}
void Logger::log(const string& inMessage, const string& inLogLevel)
{
lock_guard<mutex> guard(sMutex);
logHelper(inMessage, inLogLevel);
}
void Logger::log(const vector<string>& inMessages, const string& inLogLevel)
{
lock_guard<mutex> guard(sMutex);
for (size_t i = 0; i < inMessages.size(); i++) {
logHelper(inMessages[i], inLogLevel);
}
}
void Logger::logHelper(const std::string& inMessage,
const std::string& inLogLevel)
{
mOutputStream << inLogLevel << ": " << inMessage << endl;
}
It goes on to explain why the friend class Cleanup is introduced:
The Cleanup class is there to make sure the single Logger instance
gets deleted properly on program shutdown. This is necessary because
this implementation is dynamically allocating the Logger instance by
using the new operator in a block of code protected with a mutex. A
static instance of the Cleanup class will be created the first time
the instance() method is called. When the program terminates, the C++
runtime will destroy this static Cleanup instance, which will trigger
the deletion of the Logger object and a call to the Logger destructor
to close the file.
I find it very confusing that it states "This is necessary because...", as if there were no other alternative.
My questions:
1) Is it really necessary? Wouldn't it be enough to just have all the handling in the destructor?, like:
Logger::~Logger()
{
{
lock_guard<mutex> guard(Logger::sMutex);
delete Logger::pInstance;
Logger::pInstance = nullptr;
}
mOutputStream.close();
}
2) If the answer to 1) is "yes, it is indeed necessary!", I would like to know why.
1Professional C++, Second Edition by Marc Gregoire , Nicholas A. Solter , Scott J. Kleper Publisher: Wrox Published: October 2011

Yes, this is needed in this case. Since the book used new and handed out a pointer there is no object that will go out of scope that will cause the destructor to fire. The only way to do so is to call delete somewhere on that pointer. Instead of requiring you to do that the Cleanup class was created to do that.
All of this though can be avoided if you use a Meyers Singleton. That uses a static variable of the singleton type and returns a pointer/reference to that. That will automatically be destroyed at the end of the program unlike the book version. A Meyers Singleton looks like:
class Singleton {
public:
static Singleton* Instance() { static Singleton s; return &s; }
Singleton(const Singleton&) = delete;
void operator=(const Singleton&) = delete;
private:
Singleton() = default;
};

Related

How can I prevent Lua/Sol2 from deleting a user type when it was created outside of Lua?

I've run into an issue where a parameter (a user type) I pass into Lua function from C++ causes a crash when the Lua object is destroyed. Note I am using Sol2 in addition to Lua.
I discovered this is happening because Lua appears to be creating a copy of the parameter I passed in, and once the lua object is destroyed, it also destroys that copy. However, one of the member variables of that copy is a pointer to another object. Thus deleting it, deletes the pointer held by the original object, and when accessed causes the crash.
Is there anyway around this? Such as not copying the object but using a pointer to it, or not deleting objects not "owned" by lua/sol2.
I've created a sample project to demonstrate the issue.
LuaWrapper.h
#pragma once
#include <string>
#include <map>
#pragma warning(push, 0)
#define SOL_ALL_SAFETIES_ON 1
#include "sol.hpp"
#pragma warning(pop)
class SharedClass;
class LuaWrapper
{
public:
LuaWrapper();
~LuaWrapper();
public:
void RunFuncWithSharedClassParam(
const SharedClass& shared_class);
protected:
// Returns true if script loaded
bool LoadScriptIfNeeded(
const std::string& file_path);
virtual void RegisterUserTypes(
sol::state& lua_state);
private:
sol::function GetFunction(
const std::string& file_path,
const std::string& function_name);
protected:
typedef std::map<std::string, sol::state> LuaStates;
LuaStates m_lua_states;
private:
// No copies, do not implement
LuaWrapper(const LuaWrapper& rhs) = delete;
LuaWrapper& operator=(const LuaWrapper& rhs) = delete;
};
LuaWrapper.cpp
#include "LuaWrapper.h"
#include "SharedClass.h"
LuaWrapper::LuaWrapper()
{
}
LuaWrapper::~LuaWrapper()
{
std::cout << "~LuaWrapper Called" << std::endl;
}
void LuaWrapper::RunFuncWithSharedClassParam(
const SharedClass& shared_class)
{
sol::function FuncWithSharedClassParam = GetFunction("C:\\Users\\Omega\\source\\repos\\TestingSolution\\x64\\Debug\\LuaFile.lua", "FuncWithSharedClassParam");
if (FuncWithSharedClassParam)
{
FuncWithSharedClassParam(shared_class);
}
}
// Returns true if script loaded
bool LuaWrapper::LoadScriptIfNeeded(
const std::string& file_path)
{
if (!file_path.empty() && m_lua_states.find(file_path) == m_lua_states.end())
{
m_lua_states.emplace(file_path, sol::state());
m_lua_states[file_path].open_libraries(sol::lib::base);
RegisterUserTypes(m_lua_states[file_path]);
sol::protected_function_result result = m_lua_states[file_path].safe_script_file(file_path, &sol::script_pass_on_error);
if (!result.valid())
{
sol::error err = result;
std::string what = err.what();
std::cout << "LuaWrapper::LoadScriptIfNeeded()" << "Failed to load script:" << file_path << " - " << what << std::endl;
return false;
}
return true;
}
return false;
}
void LuaWrapper::RegisterUserTypes(
sol::state& lua_state)
{
lua_state.new_usertype<SharedClass>(
// Lua Class Name
"SharedClass",
// Member Function Binding
"Print", &SharedClass::Print);
}
sol::function LuaWrapper::GetFunction(
const std::string& file_path,
const std::string& function_name)
{
if (!function_name.empty())
{
LoadScriptIfNeeded(file_path);
LuaStates::const_iterator it = m_lua_states.find(file_path);
if (it != m_lua_states.end() && it->second[function_name].valid())
{
sol::function func = it->second[function_name];
return func;
}
}
return NULL;
}
SharedClass.h
#pragma once
class SamplePtr;
#include <string>
class SharedClass
{
public:
SharedClass(
const int id,
const std::string name);
~SharedClass();
void Print() const;
private:
const int m_id;
const SamplePtr* m_ptr;
// Don't create copies, only one instance of this specific object (with this m_id) can exist for the entire program.
SharedClass() = delete;
// Unfortunately, Lua/Sol is using this to copy (commenting out causes compile errors)
//SharedClass(const SharedClass& rhs) = delete;
SharedClass& operator=(const SharedClass& rhs) = delete;
};
SharedClass.cpp
#include "SharedClass.h"
#include "SamplePtr.h"
#include <string>
#include <iostream>
SharedClass::SharedClass(
const int id,
const std::string name) :
m_id(id),
m_ptr(new SamplePtr(name))
{
}
SharedClass::~SharedClass()
{
std::cout << "~SharedClass Called" << std::endl;
delete m_ptr;
}
void SharedClass::Print() const
{
std::cout << "Shared Classs ID: " << std::to_string(m_id) << " (" << m_ptr->m_name << ")" << std::endl;
}
SamplePtr.h
#pragma once
#include <string>
class SamplePtr
{
public:
SamplePtr(
const std::string& name);
const std::string m_name;
private:
SamplePtr() = delete;
SamplePtr(const SamplePtr& rhs) = delete;
SamplePtr& operator=(const SamplePtr& rhs) = delete;
};
SamplePtr.cpp
#include "SamplePtr.h"
SamplePtr::SamplePtr(
const std::string& name) :
m_name(name)
{
}
Main.cpp
#include <iostream>
#include "LuaWrapper.h"
#include "SharedClass.h"
int main()
{
// Once created, this object cannot be modified (const).
const SharedClass* sample0 = new SharedClass(0, "Ptr0");
// Create lua in it's own scope, so it's deleted.
{
LuaWrapper lua;
lua.RunFuncWithSharedClassParam(*sample0);
}
// Try to access sample0's pointer and it's deleted at this point (via the LuaWrapper deletion)...
sample0->Print();
}
LuaFile.lua
function FuncWithSharedClassParam(shared_class)
shared_class:Print();
end
I received a response from the Sol developer, https://github.com/ThePhD/sol2/issues/1340.
Pretty much just need to pass in the pointer for no copy!

Observer const-correctness

I am trying to implement observer pattern into my project.
Imagine simple a class method
const Buffer * data() const
{
if (m_data)
return m_data;
// read some data from input
m_data = fstream.read(1000);
// subscribe to our buffer
m_data->Subscribe(this);
return m_data;
}
This method is used to read input data, but the operation could be time consuming, it is therefore delayed.
Class Buffer is simple wrapper above std::vector, which notifies observers, when it's data being altered.
The containing class needs to be notified, when Buffer data changes.
However, since this method is marked as const, I am unable to subscribe to the Buffer.
I was able to figure out 3 solutions:
1. Cast away const-ness
// subscribe to our buffer
m_data->Subscribe(const_cast<Object*>(this));
I am not sure, whether this is correct, but it works.
2. Change const-ness of notification method and observers
vector<const IModifyObserver*> m_observers;
void Subscribe(const IModifyObserver* observer);
void Unsubscribe(const IModifyObserver* observer)
virtual void ObserveeChanged(IModifyObservable*) const override
{
m_dirty = true;
}
This one has a downfall, if I need to change properties they all have to be mutable and all functions I call must be const, which also does not make any sense.
3. Remove const from everywhere
Buffer * data();
bool Equals(Object& other);
Buffer* m_data;
This would most probably mean, that I would have to remove const from whole solution, since I can't event call Equals for two different const objects.
How to properly solve this problem?
Full Code:
#include <vector>
using namespace std;
class IModifyObservable;
// class for receiving changed notifications
class IModifyObserver
{
public:
virtual void ObserveeChanged(IModifyObservable* observee) = 0;
virtual ~IModifyObserver() = 0;
};
// class for producing changed notifications
class IModifyObservable
{
public:
// Add new subscriber to notify
void Subscribe(IModifyObserver* observer)
{
m_observers.push_back(observer);
}
// Remove existing subscriber
void Unsubscribe(IModifyObserver* observer)
{
for (auto it = m_observers.begin(); it != m_observers.end(); ++it) {
if (observer == *it) {
m_observers.erase(it);
break;
}
}
}
// Notify all subscribers
virtual void OnChanged()
{
auto size = m_observers.size();
for (decltype(size) i = 0; i < size; ++i) {
m_observers[i]->ObserveeChanged(this);
}
}
virtual ~IModifyObservable() = 0;
private:
vector<IModifyObserver*> m_observers;
};
IModifyObserver::~IModifyObserver() {}
IModifyObservable::~IModifyObservable() {}
// Example class implementing IModifyObservable
class Buffer : public IModifyObservable
{
private:
vector<char> m_data;
};
// Example class implementing IModifyObserver
class Object : public IModifyObserver
{
public:
// Both share implementation
//Buffer * data();
const Buffer * data() const
{
// Just read some data
//m_data = fstream.read(1000);
// Subscribe to our buffer
m_data->Subscribe(this);
return m_data;
}
virtual void ObserveeChanged(IModifyObservable*) override
{
m_dirty = true;
}
// This is just for example, why do I need const data method
bool Equals(const Object& other) const { return data() == other.data();
}
private:
mutable Buffer* m_data = new Buffer();
bool m_dirty;
};
int main()
{
Object obj1;
Object obj2;
auto data1 = obj1.data();
auto data2 = obj2.data();
bool equals = (obj1.Equals(obj2));
}
What gets in the way here is you deferred reading. Without this optimisation the right way would be to separate constant and non-constant methods:
const Buffer * data() const
{
return m_data;
}
void InitializeData()
{
// Just read some data
m_data = fstream.read(1000);
// Subscribe to our buffer
m_data->Subscribe(this);
}
Then optimize it the way you want:
const Buffer * data() const
{
if(m_data == nullptr)
const_cast<Object*>(this)->InitializeData();
return m_data;
}
And you don't need m_data to mutable anymore.
BTW. To make this deferred initialization work you should initialize m_data member with nullptr. Otherwise this object will be created while constructing and your if(m_data) will be always true.
UPD
So here is another solution to your problem
class Object : public IModifyObserver
{
public:
Object()
: m_data(nullptr)
, m_dataInitialized(false)
// ...
{
m_data = new Buffer(); // << Create buffer here
m_data->Subscribe(this); // << And subscribe right away
}
const Buffer * data() const
{
if(!m_dataInitialized) // << Initialize if needed
{
// Set data here
m_data->setData(fstream.read(1000)); // << Probably you want to suppress notifications here
m_dataInitialized = true;
}
return m_data;
}
// ...
private:
mutable Buffer* m_data;
mutable bool m_dataInitialized; // << Added another flag to see if data was initialized
// ...
};
I took the liberty of refactoring your code, I couldn't see where the initial call to data() would happen in your example, but I imagine it is called in a 2-phase way (construct -> then call method). Sticking with the simple rule..
#include <algorithm>
#include <memory>
#include <vector>
using namespace std;
class IModifyObservable;
// class for receiving changed notifications
class IModifyObserver
{
public:
virtual void ObserveeChanged(IModifyObservable* observee) = 0;
virtual ~IModifyObserver() = default;
};
// class for producing changed notifications
class IModifyObservable
{
public:
// This method modifies state - so non-const
void Subscribe(IModifyObserver* observer)
{
observers_.push_back(observer);
}
// This method modifies state - so non-const
void Unsubscribe(IModifyObserver* observer)
{
observers_.erase(find(begin(observers_), end(observers_), observer));
}
// Again as the internal state of the observer is modified, this is non-const
virtual void OnChanged()
{
for (auto observer : observers_) {
observer->ObserveeChanged(this);
}
}
virtual ~IModifyObservable() = default;
private:
vector<IModifyObserver*> observers_;
};
// Example class implementing IModifyObservable
class Buffer : public IModifyObservable
{
vector<char> data_;
};
// Example class implementing IModifyObserver
class Object : public IModifyObserver
{
public:
// The first call to the non-cost version triggers the lazy load...
const Buffer* data()
{
if (!data_) {
data_ = make_unique<Buffer>();
// Now start the read operation
// :
// Subscribe, I imagine you only want to do this once?
data_->Subscribe(this);
}
return data_.get();
}
// Calls to const version returns what's there...
const Buffer* data() const
{
return data_.get();
}
// This has to be non-cost as the internal state is being modified
void ObserveeChanged(IModifyObservable*) override
{
dirty_ = true;
}
// Operator uses const versions, which will use const methods
friend
bool operator==(const Object& lhs, const Object& rhs) {
if (lhs.data() && rhs.data()) {
}
return false;
}
private:
unique_ptr<Buffer> data_;
bool dirty_ = false;
};
int main()
{
Object obj1;
Object obj2;
auto data1 = obj1.data();
auto data2 = obj2.data();
bool equals = obj1 == obj2;
}
There are no hacks, it should just work...
Avoid to register in the a getter, register in initialization:
class Object : public IModifyObserver
{
public:
Object() { m_data.Subscribe(this); }
const Buffer* data() const { return m_data; }
Buffer* data() { return m_data; }
void ObserveeChanged(IModifyObservable*) override { m_dirty = true; }
private:
Buffer m_data;
bool m_dirty = false;
};
With lazy initialization, it becomes:
class Object : public IModifyObserver
{
public:
Object() { m_data.Subscribe(this); }
Buffer& data()
{
if (!m_data.is_initialized()) { m_data.initialize(); }
return m_data;
}
const Buffer& data() const
{
if (!m_data.is_initialized()) { m_data.initialize(); }
return m_data;
}
void ObserveeChanged(IModifyObservable*) override { m_dirty = true; }
private:
mutable Buffer m_data;
bool m_dirty = false;
};
Demo

Pros/Cons of using operator overloading (new/delete) to implement Singleton

I was brushing up my C++ knowledge and I chose implementing singleton to be starting point. Just I didn't want to implement the classic private constructor & static getInstance method way of doing it.
So here is a Rube Goldberg way,
class Singleton : public IDestroy {
static Singleton* iS; // Singleton instance
static int count; // number of undeleted objects
int a;
public:
Singleton(int A = 0) {
if (!iS) {
a = A;
iS = this;
}
count++;
}
void destroy() {delete this;} // way to destroy HeapOnly
int get() {
return a;
}
static void* operator new(std::size_t size);
static void operator delete(void* ptr);
protected:
// Ensuring construction of HeapOnly objects
// If object created on stack, there is no control of new operator
~Singleton() {
count--;
std::cout << "Destroyed, remaining :" << count << std::endl;
}
};
void* Singleton::operator new(std::size_t size)
{
if (iS)
return iS;
else
return ::operator new(size);
}
void Singleton::operator delete(void* ptr)
{
if (!count)
{
::operator delete(ptr);
iS = 0;
std::cout << "Cleared memory" << std::endl;
}
}
Singleton* Singleton::iS = 0;
int Singleton::count = 0;
And to work well with shared_ptr:
class IDestroy
{
public:
virtual void destroy() = 0;
};
class HeapOnlyDestroyer {
public:
void operator()(IDestroy* s) {
s->destroy();
}
};
Now, I can use the same object like:
a = new Singleton(1);
..
a->destroy();
or
shared_ptr<Singleton> s(new Singleton(1), HeapOnlyDestroyer());
I wanted to know if there are any problems in this approach, also its pros/cons over the classic way of using static getInstance method.
Cons:
It is confusing that object is not actually being created with new
Inheritance is possible that will create mess to maintain singleton functionality (could this be turned into a feature?)
First of all, what is the pro of this implementation?
Just I didn't want to implement the classic private constructor[...]
Why not?
Why not following the least surprise rule and using the Meyers Singleton?
e.g:
http://www.devarticles.com/c/a/Cplusplus/C-plus-plus-In-Theory-The-Singleton-Pattern-Part-I/4/
class Log {
public:
static Log& Instance() {
static Log theLog;
return theLog;
}
void Write(char const *logline);
bool SaveTo(char const *filename);
private:
Log(); // ctor is hidden
Log(Log const&); // copy ctor is hidden
Log& operator=(Log const&); // assign op is hidden
static std::list<std::string> m_data;
};
P.S.: Off the records, my first implementation of "singleton" was like this. After explaining the code to a college for half an hour, suddenly he asked: "Is it a singleton what you are trying to achieve?" I had to confess, I had no idea at that time, what a singleton was.

Proper Class Modeling using C++ and const

Let me preference that I mostly develop in C# and the C++ development which I have done did not fully leverage the C++ language. I am now trying to use the language as it was intended and I am pulling my hair out with const declarations in passed arguments. In the past I never used them or hacked my way into making them work with the STL.
My understanding that I would create the following function when I want to use o as readonly in the function:
void foo(const MyClass* o);
So here is my problem...code first:
#include <iostream>
#include <string>
using namespace std;
///////////////////////////////////////////////////////////
// Classes are defined in the one file for an easy post.
///////////////////////////////////////////////////////////
class ClassA {
private: // member variables
string m_name;
public: // constructors
ClassA(const string& name = "") : m_name{name} {}
virtual ~ClassA() { }
public: // accessors
const string& name() const { return m_name; }
void setName(const string& value) { m_name = value; }
};
class ClassB {
private: // member variables
string m_name;
ClassA m_child;
public: // constructors
ClassB(const string& name = "") : m_name{name} {}
virtual ~ClassB() { }
public: // accessors
const string& name() const { return m_name; }
void setName(const string& value) { m_name = value; }
ClassA* child() { return &m_child; }
void setChild(const ClassA* value) { m_child = *value; }
};
///////////////////////////////////////////////////////////
// Protoptypes are not used to save space for the post.
void doSomethingA(const ClassA* o) {
cout << "name = " << o->name() << endl << endl;
}
void doSomethingB(const ClassB* o) {
cout << "name = " << o->name() << endl << endl;
doSomethingA(o->child());
}
///////////////////////////////////////////////////////////
int main(int argc, char** argv) {
ClassA a { "My Class A" };
ClassB b { "My Class B" };
b.setChild(&a);
b.child()->setName("My New Name");
doSomethingB(&b);
return 0;
}
In main() the compiler (g++ version 4.7.2) balks in doSomethingB:
doSomethingA(o->child());
with error: passing 'const ClassB' as 'this' argument of 'ClassA* ClassB::child()' discards qualifiers [-fpermissive]
Now I am passing my classes to functions as pointers. I plan on always using pointers because I have a problem with the reference/pointer options. I'm choosing one, pointers, and sticking with it. So doSomethingA and doSomethingB I want that to be const to tell the programmer that their class is not being altered. But I only want one version of child() which I want to use sometimes as "read only" and other times allow the user to change the data within the child object (not the best method, I grant that, but there are some use cases where I need this). I even tried:
doSomethingA(const_cast<const ClassA*>(o->child()));
But that did not work.
In the past I removed the const declarations in the functions to make something like this work but now I want to use proper c++. Help please.
try
ClassA* child() const { return &m_child; }
or
const ClassA* child() const { return &m_child; }
to keep the const correctness
Also, you don't need to use pointers as long as you don't plan passing nullptr. So you can do the following:
void doSomethingB(const ClassB& o);
// in class ClassB
const ClassA& child() const { return m_child; }
ClassA& child() { return m_child; }
References still alow polymorphic stuff same way as pointers.
You're attempting to access a non-const function against a const object. You need to make the function const :
const ClassA* child() const { return &m_child; }
You can also provide a const and non-const version:
ClassA* child() { return &m_child; }
const ClassA* child() const { return &m_child; }
This way you can call non-const methods on ClassA when you have a non-const object.

How to pass argument in a singleton

I've been wondering how to pass argument to a singleton contructor. I already know how to do a singleton, but I've been unlucky to find a way to do it.
Here is my code (part of it).
Questionnary* Questionnary::getInstance(){
static Questionnary *questionnary = NULL;
if(questionnary == NULL){
cout << "Object created";
questionnary = new Questionnary();
}
else if(questionnary != NULL){
cout << "Object exist";
}
return questionnary;
}
Questionnary::Questionnary(){
cout << "I am an object";
}
//This is want i want to acheive
Questionnary::Questionnary(string name){
cout << "My name is << name;
}
Many thanks in advance
(BTW i know how and why a singleton is bad)
Let me extend Martin York's answer for your use case. I recommend using pointer for argument(s) in this particular situation, as we make use of its inherent property, that it can be "empty".
class Questionnary
{
std::string _str;
static Questionnary& getInstanceImpl(std::string* const s = nullptr)
{
static Questionnary instance{ s };
return instance;
}
Questionnary(std::string* const s)
: _str{ s ? move(*s) : std::string{} } // employ move ctor
{
if (nullptr == s)
throw std::runtime_error{ "Questionnary not initialized" };
}
public:
static Questionnary& getInstance()
{
return getInstanceImpl();
}
static void init(std::string s) // enable moving in
{
getInstanceImpl(&s);
}
Questionnary(Questionnary const&) = delete;
void operator=(Questionnary const&) = delete;
};
I find this approach less confusing, as it let's you get the instance after first initialization without (anyway discarded) arguments:
// first init
Questionnary::init("my single Questionnary");
// later on ...
Questionnary& q = Questionnary::getInstance();
Edit: Removed argument from getInstance function and a few optimizations.
You don't need to allocate the instance of singleton dynamically. It could look the following way (this is sometimes called "lazy loading singleton" ~ the instance is created late & kinda "automatically"):
#include <iostream>
#include <string>
class Questionnary
{
private:
// constructor taking string:
Questionnary(const std::string& name) : name_(name) { }
public:
static Questionnary& getInstance(const std::string& name)
{
static Questionnary q(name);
std::cout << "My name is: " << q.name_ << std::endl;
return q;
}
private:
std::string name_;
};
int main() {
Questionnary::getInstance("Josh");
Questionnary::getInstance("Harry");
}
output:
My name is: Josh
My name is: Josh
Note that constructor will be called only once right when the getInstance is called for the first time.
Have a method to create the instance to pass arguments to the constructor and you could assert in the getInstance() method if CreateInstance has not been called prior to calling it. Like:
class Questionnary
{
private:
// constructor taking string:
Questionnary(const std::string& name) : name_(name)
{
std::cout << "My name is: " << q.name_ << std::endl;
}
static Questionnary* m_instance;
public:
static void createInstance(const std::string& name)
{
assert(!m_instance);
m_instance = new Questionary(name);
}
static void destroyInstance()
{
assert(m_instance);
delete m_instance;
}
static Questionnary* Questionnary::getInstance()
{
assert(m_instance);
return m_instance;
}
private:
std::string name_;
};
//! #file singleton.h
//!
//! #brief Variadic template to make a singleton out of an ordinary type.
//!
//! This template makes a singleton out of a type without a default
//! constructor.
#ifndef SINGLETON_H
#define SINGLETON_H
#include <stdexcept>
template <typename C, typename ...Args>
class singleton
{
private:
singleton() = default;
static C* m_instance;
public:
singleton(const singleton&) = delete;
singleton& operator=(const singleton&) = delete;
singleton(singleton&&) = delete;
singleton& operator=(singleton&&) = delete;
~singleton()
{
delete m_instance;
m_instance = nullptr;
}
static C& create(Args...args)
{
if (m_instance != nullptr)
{
delete m_instance;
m_instance = nullptr;
}
m_instance = new C(args...);
return *m_instance;
}
static C& instance()
{
if (m_instance == nullptr)
throw std::logic_error(
"singleton<>::create(...) must precede singleton<>::instance()");
return *m_instance;
}
};
template <typename C, typename ...Args>
C* singleton<C, Args...>::m_instance = nullptr;
#endif // SINGLETON_H
and:
void
singleton_utest::test()
{
try
{
singleton<int, int>::instance();
UTEST_CHECK(false);
}
catch (std::logic_error& e)
{
UTEST_CHECK(true);
}
try
{
UTEST_CHECK((singleton<int, int>::create(1) == 1));
UTEST_CHECK((singleton<int, int>::instance() == 1));
}
catch (...)
{
UTEST_CHECK(false);
}
using stester0 = singleton<tester0>;
try
{
stester0::instance();
UTEST_CHECK(false);
}
catch (std::logic_error& e)
{
UTEST_CHECK(true);
}
try
{
UTEST_CHECK((stester0::create().result() == 0));
UTEST_CHECK((stester0::instance().result() == 0));
}
catch (...)
{
UTEST_CHECK(false);
}
using stester1 = singleton<tester1, int>;
try
{
stester1::instance();
UTEST_CHECK(false);
}
catch (std::logic_error& e)
{
UTEST_CHECK(true);
}
try
{
UTEST_CHECK((stester1::create(1).result() == 1));
UTEST_CHECK((stester1::instance().result() == 1));
}
catch (...)
{
UTEST_CHECK(false);
}
using stester2 = singleton<tester2, int, int>;
try
{
stester2::instance();
UTEST_CHECK(false);
}
catch (std::logic_error& e)
{
UTEST_CHECK(true);
}
try
{
UTEST_CHECK((stester2::create(1, 2).result() == 3));
UTEST_CHECK((stester2::instance().result() == 3));
}
catch (...)
{
UTEST_CHECK(false);
}
}
My version using Modern C++ that wraps an existing type:
#ifndef SINGLETON_H
#define SINGLETON_H
template <typename C, typename ...Args>
class singleton
{
private:
singleton() = default;
static C* m_instance;
public:
~singleton()
{
delete m_instance;
m_instance = nullptr;
}
static C& instance(Args...args)
{
if (m_instance == nullptr)
m_instance = new C(args...);
return *m_instance;
}
};
template <typename C, typename ...Args>
C* singleton<C, Args...>::m_instance = nullptr;
#endif // SINGLETON_H
Here is what in looks like in a unit test:
int &i = singleton<int, int>::instance(1);
UTEST_CHECK(i == 1);
tester1& t1 = singleton<tester1, int>::instance(1);
UTEST_CHECK(t1.result() == 1);
tester2& t2 = singleton<tester2, int, int>::instance(1, 2);
UTEST_CHECK(t2.result() == 3);
The problem with this is that instance() requires arguments on each call but only uses them on the first (as noted above). Default arguments cannot be used generally. It may be better to use a create(Args...) method which must precede the call of instance() or throw an exception.