I am using CRTP to create a counter class, similar to Object Counter
Additionally, classes that derive from this counter also should not be destructible.
It will look something like this
template <typename DERIVED_CLASS, std::size_t size = 0>
class Counter{
private:
~Counter() = delete;
protected:
std::vector<DERIVED_CLASS*> created;
Counter(){}
public:
//More stuff later
};
class A : public Counter<A>{
public:
A(){std::cout << "A created" << std::endl;}
//More stuff later
};
A a;
int main(){
/* All should be invalid
A b;
A c{a};
A* pA = new A;
*/
return 0;
}
The creation of a
should be the only permitted usage for creating/deleting objects of these types. They should not be copyable, and should last for the entirety of the program life, therefore should not be destructed.
However, I get the the following errors and diagnostic messages
base class 'Counter<A>' has private destructor
destructor of 'A' is implicitly deleted because base class 'Counter<A>' has a deleted destructor
~Counter' has been explicitly marked deleted here
attempt to use a deleted function
Edit:
Just clarifying a few things.
Of course the object will be destructed at program exit. This is desired behaviour. It only should not be destructible by the user or during program life.
Secondly, multiple objects can be created. This is not a create once kind of thing. Many can be created, but not copied or deleted.
Edit: Code for @joerbrech's comment
template <typename DERIVED_CLASS, std::size_t size = 0>
class Counter{
private:
Counter(Counter const &) = delete;
Counter& operator=(Counter const &) = delete;
protected:
~Counter(){}
Counter(){}
public:
template <typename... DERIVED_ARGS>
static DERIVED_CLASS& create(DERIVED_ARGS... args){
DERIVED_CLASS* pDerived = new DERIVED_CLASS(args...);
//Save the pointer into a static collection
return *pDerived;
}
//More stuff later
};
class A: public Counter<A>{
using Base = Counter<A>;
friend Base;
A(int x){}
//More stuff later
};
A& a = A::create(1);
int main(){
A& b = A::create(2); //Works (bad)
// A c(3); //Fails (good)
// A* pA = new A(4); //Fails (good)
(void)b; //To silence unused variable warning
return 0;
}