C++ Link Error when I was implementing template Singleton class - c++

I'm implementing a Singleton template in C++. I try to achieve thread-safe by std::call_once and std::once_flag, but somehow link error happens.
singleton.h
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
#include <boost/noncopyable.hpp>
#include <mutex>
template<typename T>
class Singleton : boost::noncopyable {
public:
Singleton() = delete;
static T& getInstance() {
std::call_once(init_flag_, &Singleton::init);
return *val_;
}
private:
static void init() {
val_ = new T();
}
private:
static std::once_flag init_flag_;
static T* val_;
};
#endif // _SINGLETON_H_
test_singleton.cc
#include "singleton.h"
#include <iostream>
class Log {
public:
void log() {
std::cout << "log" << std::endl;
}
};
int main() {
Log & logger = Singleton<Log>::getInstance();
logger.log();
}
And my g++ statement is
g++ -std=c++14 -pthread -o test test_singleton.cc
Error message:
/tmp/ccoxQBXl.o: In function `Singleton<Log>::getInstance()':
test_singleton.cc:(.text._ZN9SingletonI3LogE11getInstanceEv[_ZN9SingletonI3LogE11getInstanceEv]+0x2c): undefined reference to `Singleton<Log>::init_flag_'
test_singleton.cc:(.text._ZN9SingletonI3LogE11getInstanceEv[_ZN9SingletonI3LogE11getInstanceEv]+0x38): undefined reference to `Singleton<Log>::val_'
/tmp/ccoxQBXl.o: In function `Singleton<Log>::init()':
test_singleton.cc:(.text._ZN9SingletonI3LogE4initEv[_ZN9SingletonI3LogE4initEv]+0x11): undefined reference to `Singleton<Log>::val_'
collect2: error: ld returned 1 exit status

Finally got it. The only problem is I didn't initialize the static variables.
For C++17, inline keyword allows initialization within class.
#ifndef SINGLETON_H_
#define SINGLETON_H_
#include <boost/noncopyable.hpp>
#include <mutex>
template<typename T>
class Singleton : boost::noncopyable {
public:
Singleton() = delete;
static T& getInstance() {
std::call_once(init_flag_, &Singleton::init);
return *val_;
}
private:
static void init() {
val_ = new T();
}
private:
static inline std::once_flag init_flag_{};
static inline T* val_ = nullptr;
};
#endif // SINGLETON_H_

Related

Class Template Static Member Initialized Twice

There is an issue with my Instance class in that I noticed a difference in behavior that stems from two methods of initializing a static member.
The class template Instance is keeping track of a unique count. The unique count is being used to keep track of the amount of derived classes for a specific type. It is also used to assign a unique id/index for derived classes.
The first is initialized as follows:
template<typename Derived, typename Key>
Key Instance<Derived, Key>::count_static_assign{ std::numeric_limits<Key>::min() };
The second is initialized as such:
template<typename Derived, typename Key>
Key Instance<Derived, Key>::count_default{ 0 };
Program's output
1 1
2 1
I expect the two values to be equal because they should both be incrementing. However count_static_assign, is giving the wrong output as it appears to reset and be equal to 1 twice. Thus, I would like to know why there is a difference in behavior between these two static variables.
Here are the files for the program that demonstrates the error.
Instance.h
#ifndef INSTANCE_H
#define INSTANCE_H
#include <cinttypes>
#include <limits>
#include <iostream>
template<typename Derived, typename Key = std::uint16_t>
class Instance {
public:
using KeyType = Key;
static KeyType count_static_assign;
static KeyType count_default;
public:
Instance() = default;
virtual ~Instance() = default;
virtual KeyType getInstance() const = 0;
protected:
static KeyType generate() {
count_static_assign++;
count_default++;
std::cout << count_default << ' ' << count_static_assign << '\n';
return count_default;
}
};
//doesn't behave as expected
template<typename Derived, typename Key>
Key Instance<Derived, Key>::count_static_assign{ std::numeric_limits<Key>::min() };
//behaves as expected
template<typename Derived, typename Key>
Key Instance<Derived, Key>::count_default{ 0 };
#endif
Base.h
#ifndef BASE_H
#define BASE_H
#include <cinttypes>
#include <typeindex>
#include <memory>
#include "Instance.h"
class Base : public Instance<Base>
{
public:
Base(){}
~Base(){}
};
template<typename Derived>
class CRTPBase : public Base {
public:
static const KeyType STATIC_TYPE;
CRTPBase() {}
virtual ~CRTPBase() {}
virtual KeyType getInstance() const override {
return STATIC_TYPE;
}
};
template<typename Derived>
const typename CRTPBase<Derived>::KeyType CRTPBase<Derived>::STATIC_TYPE = CRTPBase<Derived>::generate();
#endif
Foo.h
#ifndef FOO_H
#define FOO_H
#include "Base.h"
struct Foo : public CRTPBase<Foo> {
Foo();
~Foo();
};
#endif
Foo.cpp
#include "Foo.h"
Foo::Foo()
{
}
Foo::~Foo()
{
}
Bar.h
#ifndef BAR_H
#define BAR_H
#include "Base.h"
struct Bar : public CRTPBase<Bar>
{
public:
Bar();
~Bar();
};
#endif
Bar.cpp
#include "Bar.h"
Bar::Bar()
{
}
Bar::~Bar()
{
}
main.cpp
#include "Foo.h"
#include "Bar.h"
int main() {
Foo foo;
Bar bar;
std::cin.get();
}
If it matters, I am using Visual Studio 2017(Full Version-191426433) to compile. In addition, debug and release mode make no difference.
This code looks correct to me: count_default and count_static_assign have constant expressions as initializers, so they must be initialized before any dynamic initialization happens. STATIC_TYPE is dynamic initialization.
OP reports that changing std::numeric_limits<Key>::min() to 0 fixes the behaviour of the program, so I would conjecture that the compiler has a bug that it does not consider the constexpr function std::numeric_limits<Key>::min() to be a constant expression.
To work around this you could try some other way of coming up with a constant initializer for count_static_assign, e.g. a constexpr function that you write yourself, or a specialization for each type that you do use.

Linker in some cases complains about undefined ref. to template class static object member

I'm new to template programming. While implementing singleton class using template, I found in some cases (as below shows) the linker complains error:
undefined reference to `Singleton<Test>::_lock'
However, if I change following statement
template<> Mutex Singleton<Test>::_lock;
to
template<> Mutex Singleton<Test>::_lock(1);
it compiles and runs without error.
Could someone helps me out and explains why in below case the compiling fails?
#include <iostream>
#include <pthread.h>
class Mutex {
public:
Mutex(){ pthread_mutex_init(&mMutex, NULL); }
Mutex(int dummy){ pthread_mutex_init(&mMutex, NULL); }
~Mutex(){ pthread_mutex_destroy(&mMutex); }
Mutex(const Mutex&) = delete;
Mutex& operator = (const Mutex&) = delete;
int lock(){ return -pthread_mutex_lock(&mMutex); }
void unlock(){ pthread_mutex_unlock(&mMutex); }
// Manages the mutex automatically. It'll be locked when Autolock is
// constructed and released when Autolock goes out of scope.
class Autolock {
public:
explicit Autolock(Mutex& mutex) : mLock(mutex) { mLock.lock(); }
~Autolock() { mLock.unlock(); }
private:
Mutex& mLock;
};
private:
pthread_mutex_t mMutex;
};
template <typename T>
class Singleton: {
public:
static T& Instance() {
Mutex::Autolock _l(_lock);
if(nullptr == _instance) {
_instance = new T();
}
return *_instance;
}
virtual ~Singleton(){}
Singleton() = default;
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
static T* _instance;
static Mutex _lock;
};
class Test: public Singleton<Test> {
public:
void dis() {std::cout << "hi" << std::endl;}
};
template<> Mutex Singleton<Test>::_lock;
template<> Test* Singleton<Test>::_instance(nullptr);
template class Singleton<Test>;
int main()
{
Test::Instance().dis();
return 0;
}

Qt Singleton implementation

I was looking for a Singleton Qt implementation and found this. but I have some question about it.
What is the purpose of making create a QBasicAtomicPointer ?
What is the point in qCallOnce of using testAndSetRelaxed if previously we have used fetchAndStoreAcquire ? Isn't the acquire semantic already preventing any memory reordering after it ?
What is the purpose of the qCallOncePerThread function ? Isn't qCallOnce already thread-safe ?
I copy the contents of the suggested implementation here:
call_once.h
#ifndef CALL_ONCE_H
#define CALL_ONCE_H
#include <QtGlobal>
#include <QAtomicInt>
#include <QMutex>
#include <QWaitCondition>
#include <QThreadStorage>
#include <QThread>
namespace CallOnce {
enum ECallOnce {
CO_Request,
CO_InProgress,
CO_Finished
};
Q_GLOBAL_STATIC(QThreadStorage<QAtomicInt*>, once_flag)
}
template <class Function>
inline static void qCallOnce(Function func, QBasicAtomicInt& flag)
{
using namespace CallOnce;
#if QT_VERSION < 0x050000
int protectFlag = flag.fetchAndStoreAcquire(flag);
#elif QT_VERSION >= 0x050000
int protectFlag = flag.fetchAndStoreAcquire(flag.load());
#endif
if (protectFlag == CO_Finished)
return;
if (protectFlag == CO_Request && flag.testAndSetRelaxed(protectFlag,
CO_InProgress)) {
func();
flag.fetchAndStoreRelease(CO_Finished);
}
else {
do {
QThread::yieldCurrentThread();
}
while (!flag.testAndSetAcquire(CO_Finished, CO_Finished));
}
}
template <class Function>
inline static void qCallOncePerThread(Function func)
{
using namespace CallOnce;
if (!once_flag()->hasLocalData()) {
once_flag()->setLocalData(new QAtomicInt(CO_Request));
qCallOnce(func, *once_flag()->localData());
}
}
#endif // CALL_ONCE_H
singleton.h
#ifndef SINGLETON_H
#define SINGLETON_H
#include <QtGlobal>
#include <QScopedPointer>
#include "call_once.h"
template <class T>
class Singleton
{
private:
typedef T* (*CreateInstanceFunction)();
public:
static T* instance(CreateInstanceFunction create);
private:
static void init();
Singleton();
~Singleton();
Q_DISABLE_COPY(Singleton)
static QBasicAtomicPointer<void> create;
static QBasicAtomicInt flag;
static QBasicAtomicPointer<void> tptr;
bool inited;
};
template <class T>
T* Singleton<T>::instance(CreateInstanceFunction create)
{
Singleton::create.store(create);
qCallOnce(init, flag);
return (T*)tptr.load();
}
template <class T>
void Singleton<T>::init()
{
static Singleton singleton;
if (singleton.inited) {
CreateInstanceFunction createFunction = (CreateInstanceFunction)Singleton::create.load();
tptr.store(createFunction());
}
}
template <class T>
Singleton<T>::Singleton() {
inited = true;
};
template <class T>
Singleton<T>::~Singleton() {
T* createdTptr = (T*)tptr.fetchAndStoreOrdered(nullptr);
if (createdTptr) {
delete createdTptr;
}
create.store(nullptr);
}
template<class T> QBasicAtomicPointer<void> Singleton<T>::create = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
template<class T> QBasicAtomicInt Singleton<T>::flag = Q_BASIC_ATOMIC_INITIALIZER(CallOnce::CO_Request);
template<class T> QBasicAtomicPointer<void> Singleton<T>::tptr = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
#endif // SINGLETON_H
How to use
// myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
class MyClass : public QObject
{
Q_OBJECT
private:
MyClass(QObject* parent = 0);
static MyClass* createInstance();
public:
~MyClass();
static MyClass* instance();
};
#endif // MYCLASS_H
// myclass.cpp
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
#include "singleton.h"
MyClass::MyClass(QObject* parent):
QObject(parent)
{
}
MyClass* MyClass::createInstance()
{
return new MyClass();
}
MyClass::~MyClass()
{
}
MyClass* MyClass::instance()
{
return Singleton<MyClass>::instance(MyClass::createInstance);
}
#endif // MYCLASS_H
main.cpp
#include <QTextStream>
#include "myclass.h"
#define MyClassInstance Singleton<MyClass>::instance()
int main(int argc, char* argv[])
{
QTextStream(stdout) << MyClass::instance()->metaObject()->className() << endl;
return 0;
}
I think that is will be enough to use next singleton implementation. As I remember, C++11 gurantees that there will be only one instancing/initialization for a static variable.
Original problem was in case, when more than one thread tries to access an instance in same time and there were possible a situation, when singleton was created twice.
template <typename T, typename D = T>
class Singleton
{
friend D;
static_assert(std::is_base_of_v<T, D>, "T should be a base type for D");
public:
static T& instance();
private:
Singleton() = default;
~Singleton() = default;
Singleton( const Singleton& ) = delete;
Singleton& operator=( const Singleton& ) = delete;
};
template <typename T, typename D>
T& Singleton<T, D>::instance()
{
static D inst;
return inst;
}
// Usage:
class MyClass : public Singleton<MyClass>
{
public:
void foo(){}
};
// Access:
MyClass::instance().foo();
Main concept of using Singleton pattern is to restrict the instantiation to certain number of objects, in common use to one.
Q1 : Atomic pointer
Atomic operations are done without interruption , so handled multi-thread instance calls.
Q2 : point of qCallOnce
This function checks if any other threads are executing and if so wait for CO_finished flag in
do {
QThread::yieldCurrentThread();
}
while (!flag.testAndSetAcquire(CO_Finished, CO_Finished));
Q3 : point of qCallOncePerThread
if (!once_flag()->hasLocalData()) {
once_flag()->setLocalData(new QAtomicInt(CO_Request));
I think to handle LocalData of singleton class per each thread instacnes

C++ Singleton undefined reference to

I am new to C++ and trying to understand the Singleton Pattern in C++.
myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
class Myclass {
public:
static Myclass* getInstance();
private:
Myclass(){}
Myclass(Myclass const&){}
Myclass& operator=(Myclass const&){}
static Myclass* m_instance;
};
#endif // MYCLASS_H
myclass.cpp
#include "myclass.h"
Myclass* Myclass::getInstance() {
if (!m_instance) {
m_instance = new Myclass;
}
return m_instance;
}
The compiler can't compile. I get the following error, on all 3 lines with m_instance:
error: undefined reference to `Myclass::m_instance'
You forgot to add:
Myclass* Myclass::m_instance = 0; // or NULL, or nullptr in c++11
right under #include "myclass.h".

template static variable undefined in class ctor

I have defined below hierarchy of classes, my intention is to design a generic class that allows me to iterate over enum objects (C++11 is not allowed to be used unfortunately). The class definition and test program are:
// base.h
#include <set>
template <typename T>
class Base
{
protected:
explicit Base(int value);
typedef typename std::set< Base<T>* > instances;
static instances s_instances;
int value_;
public:
int get_value() const { return value_ ; }
};
template <typename T>
Base<T>::Base(int value): value_(value)
{
s_instances.insert(this);
}
// derived.h
#include "base.h"
class Derived : public Base<Derived>
{
protected:
explicit Derived(int value): Base<Derived>(value) { }
public:
static const Derived value1;
};
// test.cc
#include "derived.h"
template<>
Base<Derived>::instances Base<Derived>::s_instances;
const Derived Derived::value1(1);
int main(int argc, char *argv[])
{
using std::cout;
using std::endl;
cout << Derived::value1.get_value() << endl;
}
On compilation using g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, it gives me below linking error:
"
g++ test.cc -o test
/tmp/ccOdkcya.o: In function `Base<Derived>::Base(int)':
test.cc:(.text._ZN4BaseI7DerivedEC2Ei[_ZN4BaseI7DerivedEC5Ei]+0x28): undefined reference to `Base<Derived>::s_instances'
collect2: ld returned 1 exit status
"
Can anyone please suggest what am I missing in above code?
Thanks!
Static data members are declared in class definitions and defined outside the class definition. Like this:
// header:
class C {
static int i;
};
// source:
int C::i = 17;
With a template, you typically don't put any code in source files, so the definition goes in the header:
// header:
template <class T>
class C {
static int i;
};
template <class T>
int C<T>::i = 17;
Be aware that s_instances might not have been initialized before it is used.
You can only write
// template<> -> you should not write this in this case.
Base<Derived>::instances Base<Derived>::s_instances;
If you have provided an explicit specialization of Base<Derived>, such as :
class Derived;
template <>
class Base<Derived>
{
protected:
explicit Base(int value);
typedef typename std::set< Base<Derived>* > instances;
static instances s_instances;
int value_;
public:
int get_value() const { return value_ ; }
};
Otherwise, you have to stick to writing:
template<typename T>
typename Base<T>::instances Base<T>::s_instances;