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.
Related
I like to create a registry of templated classes adressed through their polymorphic anonymous base-class. In order to construct these classes I need to store the type of the used template class in the base-class. I woulod like to make the design slim and pass the template class in the constructor of the baseclass through a custom templated constructor.
However my code fails, and i cannot figure out what the correct formulation would be. Any help appriciated:
#include <vector>
#include <string>
#include <typeinfo>
#include <memory>
class Store_Base {
const std::string stored_type_name_;
protected: //ctor
template<class Tstored>
Store_Base() : stored_type_name_(typeid(Tstored).name()) {};
protected: // dtor
virtual ~Store_Base() = default;
public:
std::string get_type_name() const {return stored_type_name_;}
};
template <class Tstored>
class Store : public Store_Base {
const Tstored stored_;
public: //ctor
Store(const Tstored stored)
: Store_Base<Tstored>(), stored_(stored) {}; // !!! compile-error
public:
Tstored get_stored() const {return stored_;}
};
int main() {
std::vector<std::unique_ptr<Store_Base>> my_vec;
my_vec.emplace_back(std::make_unique< Store<int> >(42));
my_vec.at(0)->get_type_name(); // >>> i
((Store<int>*)(my_vec.at(0).get()))->get_stored(); // >>> 42
return 0;
}
This
Store(const Tstored stored)
: Store_Base<Tstored>()
is wrong, because it attempts to initialize the base class Store_Base<Tstored>, but Store_Base is not a template. The base class to be initialized is Store_Base not Store_Base<Tstored>.
The way to call a templated constructor is to have the template argument deduced. See here C++ template constructor.
You can use a tag to enable deduction:
#include <vector>
#include <string>
#include <typeinfo>
#include <memory>
template <typename T>
class Tag{};
class Store_Base {
const std::string stored_type_name_;
protected: //ctor
template<class Tstored>
Store_Base(Tag<Tstored>) : stored_type_name_(typeid(Tstored).name()) {};
protected: // dtor
virtual ~Store_Base() = default;
public:
std::string get_type_name() const {return stored_type_name_;}
};
template <class Tstored>
class Store : public Store_Base {
const Tstored stored_;
public: //ctor
Store(const Tstored stored)
: Store_Base(Tag<Tstored>{}), stored_(stored) {}; // !!! compile-error
public:
Tstored get_stored() const {return stored_;}
};
int main() {
std::vector<std::unique_ptr<Store_Base>> my_vec;
my_vec.emplace_back(std::make_unique< Store<int> >(42));
my_vec.at(0)->get_type_name(); // >>> i
((Store<int>*)(my_vec.at(0).get()))->get_stored(); // >>> 42
return 0;
}
Note that I didn't change more than necessary and that this code still fails to compile due to the destructor of Store_Base being protected, ie std::unique_ptr cannot access it.
I'm having an issue where I've created a somewhat tangled hierarchy involving templates. The result is I'm having to put some code in the wrong header files just to get it to compile, and compilation is now fragile (I don't know if I can keep this project compiling if just the right function needs to be added.)
So I'm looking for a way to resolve this so that the code is nicely divided into proper files.
So without further ado, here is the code:
TemplatedBase.h
template <typename T> struct TemplatedBase
{
T value;
void go();
};
Derived.h
struct Derived : public TemplatedBase<int>
{
void hello()
{
printf("HI %d\n", value);
}
};
template <typename T> void TemplatedBase<T>::go()
{
// TemplatedBase<T> NEEDS USE OF Derived!!
// So TemplatedBase<T>::go() is appearing here in Derived.h,
// that's the only way I could get it to compile and it seems really
// out of place here.
Derived der;
der.hello();
}
main.cpp
#include <stdio.h>
#include "Derived.h"
int main(int argc, const char * argv[])
{
Derived d;
d.go();
return 0;
}
Isn't there a way I can put TemplatedBase<T>::go() into a file like TemplatedBase.cpp? Alas, it doesn't seem to work (you will see Undefined symbol: TemplatedBase<int>::go() in XCode at least).
You could do it by explicitly instantiating the template with a particular type in the cpp file:
// TemplatedBase.cpp
#include "TemplatedBase.h"
#include "Derived.h"
template <typename T>
void TemplatedBase<T>::go()
{
// TemplatedBase<T> NEEDS USE OF Derived!!
// So TemplatedBase<T>::go() is appearing here in Derived.h,
// that's the only way I could get it to compile and it seems really
// out of place here.
Derived der;
der.hello();
}
template struct TemplatedBase<int>; // This will make it work but now you can only use `TemplatedBase<int>`
// More instantiations go here...
But I wouldn't recommend doing this as this restricts what types you are able to use in TemplatedBase<T> (You'd have to manually add every single type yourself). So instead, use a templated type inside the go() member function (The trick here is that template parameters are not evaluated immediately):
// TemplatedBase.h
struct Derived; // Forward declaration
template <typename T>
struct TemplatedBase
{
T value;
void go()
{
go_impl();
}
private:
template <typename X = Derived>
void go_impl()
{
X der;
der.hello();
}
};
// Derived.h
#include "TemplatedBase.h"
struct Derived : public TemplatedBase<int>
{
void hello()
{
printf("HI %d\n", value);
}
};
Note: BTW, since C++20, one can just do:
// TemplatedBase.h
struct Derived; // Forward declaration
template <typename T>
struct TemplatedBase
{
T value;
void go()
{
[] <typename X = Derived>() {
X d;
d.hello();
}();
}
};
TemplatedBase and Derived are really coupled, so sharing the same header might be a viable option.
Else, you can create a file for your template definition (Header guards omitted):
// TemplatedBase.h
// Public header
#include "TemplatedBaseDecl.h"
#include "TemplatedBaseImpl.h"
// TemplatedBaseDecl.h
template <typename T>
struct TemplatedBase
{
T value;
void go();
};
// TemplatedBaseImpl.h
#include "TemplatedBaseDecl.h"
#include "Derived.h"
template <typename T> void TemplatedBase<T>::go()
{
Derived der;
der.hello();
}
// Derived.h
// Public header
#include "TemplatedBaseDecl.h" // Cannot use "TemplatedBase.h"
struct Derived : public TemplatedBase<int>
{
void hello()
{
printf("HI %d\n", value);
}
};
I have a class A with the following declaration (A.h file):
#ifndef __A_DEFINED__
#define __A_DEFINED__
class A
{
public:
template<typename T> inline void doThat() const;
};
#endif
and a class B deriving from that class (B.h file):
#ifndef __B_DEFINED__
#define __B_DEFINED__
#include <iostream>
#include "A.h"
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
#endif
So far, so good. My issue is that the function A::doThat() uses B::doThis():
template<typename T> inline void A::doThat() const { B b; b.doThis(); }
Usually, the circular dependency would not be an issue because I would just define A::doThat() in the .cpp file. In my case however, doThat is a template function so I can't do that.
Here are the solutions I have envisioned so far:
Defining the template function A::doThat() in a .cpp file. The issue with that is that I need to instantiate explicitly all the calls with various template arguments (there might be many in the real case).
After the declaration of the A class in A.h, add #include "B.h" and then define the A::doThat() function. This works fine in visual studio but g++ does not like it.
Is there a neat way to solve this problem?
EDIT: In the real case, there is not just one child class B, but several (B, C, D, etc.) The function A::doThat() depends on all of them. The function B::doThis() is also templated.
A default template parameter for the B class could work:
#include <iostream>
// include A.h
class B;
class A
{
public:
template<typename T, typename U = B> inline void doThat() const
{
U b; b.doThis();
}
};
// include B.h
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
// main
int main()
{
A a;
a.doThat<int>();
}
Usually the best way to allow a parent to call a child function is to declare the function as a pure virtual function in the parent and override it in the children.
#include <iostream>
class A
{
public:
virtual ~A() = default;
template<typename T> inline void doThat() const
{
// do some other stuff
doThis();
}
virtual void doThis() const = 0; // pure virtual function
};
class B: public A
{
public:
void doThis() const override
{
std::cout << "do this!" << std::endl;
}
};
int main()
{
B b;
A* ap = &b;
ap->doThat<int>();
}
The following does work with g++:
File A.h:
#ifndef __A_DEFINED__
#define __A_DEFINED__
class A
{
public:
template<typename T> inline void doThat() const;
};
#include "B.h"
template<typename T> inline void A::doThat() const { B b; b.doThis(); }
#endif
File B.h:
#include <iostream>
#include "A.h"
// We check for the include guard and set it AFTER the inclusion of A.h
// to make sure that B.h is completely included from A.h again.
// Otherwise the definition of A::doThat() would cause a compiler error
// when a program includes B.h without having included A.h before.
#ifndef __B_DEFINED__
#define __B_DEFINED__
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
#endif
File test_A.cpp:
// In this test case we directly include and use only A.
#include "A.h"
#include "A.h" // We test whether multiple inclusion causes trouble.
int main() {
A a;
a.doThat<int>();
}
File test_B.cpp:
// In this test case we directly include and use only B.
#include "B.h"
#include "B.h" // We test whether multiple inclusion causes trouble.
int main() {
B b;
b.doThat<int>();
b.doThis();
}
Alternative Idea:
I do not know whether you (or some coding conventions) insist on separate header files for each class, but if not the following should work:
You can put the definitions of class A and class B and of the member function template A::doThat<typename>() (in this order) together in one header file AandB.h (or whatever name you like).
This cries for polymorphism. There are two options using polymorphism:
Dynamic polymorphism, i.e. make A an abstract base class and call doThis() virtually:
struct A
{
virtual void do_this() const = 0;
template<typename T>
void doThat() const { doThis(); }
};
struct B : A
{
void doThis() const override { /* ... */ }
};
Of course, this only works if doThis() is not templated. If you need that, you could use
Static polymorphism, i.e. CRTP, when
template<typename Derived>
struct A
{
template<typename T>
void doThat() const { static_cast<const Derived*>(this)->template doThis<T>(); }
};
struct B : A<B>
{
template<typename T>
void doThis() const { /* ... */ }
};
If (as in your example code) B::doThis() is not called for the same object, but for some temporary, you could
template<typename typeB>
struct A
{
template<typename T>
void doThat() const { typeB b; b.template doThis<T>(); }
};
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
My base template class is in Base.h:
#include <iostream>
using std::cout;
using std::endl;
#ifndef BASE_H
#define BASE_H
template<typename T>
class Base
{
public:
Base();
Base(T a0, T b0);
void display();
private:
T a,b;
T sum();
};
#endif // BASE_H
template<typename T>
Base<T>::Base():a(0),b(0){}
template<typename T>
Base<T>::Base(T a0, T b0):a(a0),b(b0){}
template<typename T>
T Base<T>::sum()
{
return a+b;
}
template<typename T>
void Base<T>::display()
{
cout<<"The sum is: "<<sum()<<endl;
}
And my Derived.h file is:
#ifndef DERIVED_H
#define DERIVED_H
#include <Base.h>
template<typename T>
class Derived : public Base<T>
{
public:
Derived(){}
Derived(T a0, T b0);
void display1();
};
#endif // DERIVED_H
template<typename T>
Derived<T>::Derived(T a0, T b0):Base<T>(a0,b0) {}
template<T>
void Derived<T>::display1()
{
this->display();
}
I do know implementation of template class should not be in .cpp file, but why there is undefined error when I put the separate header files in different .h file?
The error is showed as follows (with code::blocks):
***include\Base.h|24|error: redefinition of 'Base<T>::Base()'|
include\Base.h|24|error: 'Base<T>::Base()' previously declared here|***
Two issues. First, your #include guards are wrong. You are only guarding the class declaration:
#ifndef BASE_H
#define BASE_H
template<typename T>
class Base
{
...
};
#endif // BASE_H
... definitions of Base<T> ...
If Base.h is #included twice, you'll only get one class declaration (good) but then you'll get multiple definitions of all the member functions (bad).
The #include guards should guard the entire file. Move the #ifndef to the first line and the #endif to the last line.
Second issue, if you provide your member function definitions in the header but external to the class declaration, you have to mark the function as inline (this can be done either in the declaration or the definition, but personally I prefer the declaration). That is:
template <typename T>
class Base {
...
inline Base();
inline void display();
inline T sum();
};
// definitions...