C++ (sort of) factory - c++

I've seen a number of posts regarding C++ factories, but so far I haven't seen a solution that solves my problem. (Though I may be missing something.)
Example console app:
#include <memory>
#include <map>
#include <iostream>
using namespace std;
class ResourceManager;
/// abstract base class
class Identity
{
public:
int Id() const { return _id; }
/// make this an abstract class
virtual ~Identity() = 0 {}
protected:
Identity() { _id = _nextId++; }
private:
int _id;
static int _nextId;
};
int Identity::_nextId = int();
/// derived classes
class Component : public Identity
{
friend class ResourceManager;
public:
~Component() { }
};
class Entity : public Identity
{
friend class ResourceManager;
public:
~Entity() { }
};
class ResourceManager
{
public:
template<typename T>
T& Create()
{
auto ptr = std::make_shared<T>();
auto id = ptr->Id();
_resources[id] = std::move(ptr);
return *dynamic_pointer_cast<T>(_resources[id]);
}
private:
std::map<int, std::shared_ptr<Identity>> _resources;
};
int main(int argc, char *argv[])
{
cout << "Factory test" << endl;
ResourceManager r;
auto& e = r.Create<Entity>();
cout << "e.id = " << e.Id() << endl;
Entity e2;
cout << "e2.id = " << e2.Id() << endl;
Component c;
cout << "c.id = " << c.Id() << endl;
std::getchar();
}
I need to make sure that only ResourceManager can instantiate Entity, Component and any classes that derive from them.
I've looked and adding ResourceManager as a friend class to Identity, and making the constructors private or protected, with no success. (This could be a blind alley, or just an implementation problem on my end.)
Any suggestions?
Update and Edit
Replaced code with compilable example. Although the constructor for Identity() is protected, I can still directly instantiate derived classes.

Following should work:
friend class ResourceManager; should be in each derivated classes.
(friend is not inherited).
class ResourceManager;
/// abstract base class
class Identity
{
public:
int Id() const { return _id; }
/// make this an abstract class
virtual ~Identity() = 0;
// Forbid any copy
Identity(const Identity&) = delete;
Identity(const Identity&&) = delete;
Identity& operator = (const Identity&) = delete;
Identity& operator = (Identity&&) = delete;
protected:
Identity() { _id = _nextId++; }
private:
int _id;
static int _nextId;
};
// empty destructor
Identity::~Identity() {}
int Identity::_nextId = 0;
/// derived classes
class Component : public Identity
{
friend class ResourceManager;
public:
~Component() { }
protected:
Component() = default;
};
class Entity : public Identity
{
friend class ResourceManager;
public:
~Entity() { }
protected:
Entity() = default;
};
class ResourceManager
{
public:
template<typename T>
T& Create()
{
std::unique_ptr<T> ptr(new T);
T& res = *ptr;
_resources[ptr->Id()] = std::move(ptr);
return res;
}
/// TODO: need to make sure that resource ID is actually of type T
/// and that _resources contains ID.
template<typename T>
T* Get(int id)
{
auto it = _resources.find(id);
if (it == _resources.end()) {
return nullptr;
}
return dynamic_cast<T*>(it->second.get());
}
private:
std::map<int, std::unique_ptr<Identity>> _resources;
};
Note that since ResourceManager owns the resource I change std::shared_ptr to std::unique_ptr.
I fixed ResourceManager::Get with invalid id.

Have you tried a protected construtor?
class Identity
{
friend class ResourceManager;
public:
int Id() { return _id; }
virtual ~Identity() = 0;
protected:
Identity() {
_id = _nextId++;
}
private:
static int _nextId;
// do not forget to put "int Identity::_nextId = 0;" in a source file
};
Identity::~Identity()
{
}
But you need to repeat this pattern in every derived class. Thus making ResourceManager a friend and making the constructor private or protected.

Related

Keep track of object types

What I'm trying to achieve is to keep track of what types of objects we're created that inherit from a base class. If a class inherits from the base class but is not instantiated in an object I'm not that interested in tracking that (this condition can be included or not depending if the implementation is easier or not)
Dummy example:
template <typename T>
class Person
{
public:
Person() {
T* x;
container.push_back(x);
}
virtual ~Person() {}
private:
static heterogeneous_container container;
};
class Employee : public Person <Employee>
{
};
class Employee2 : public Employee
{
};
Also, I would like this to work for chained inheritance. Is it possible that when I instantiate an Employee2, the base class Person will add an Employee2 type pointer in the container?
As for the heterogeneous container, I think this can be used link
I think what you want is more like:
class Person
{
public:
Person() {
objects.push_back(this);
}
virtual ~Person() {
objects.erase(this);
}
private:
static std::set<const Person*> objects;
};
class Employee : public Person
{
};
class Employee2 : public Employee
{
};
With this approach, you can enquire the dynamic type of the most-derived object that each of the pointers in the container points to.
Note that the objects set has to contain the pointers, not the type_info for each object. The problem is that inside the constructor for the Person sub-object of an Employee2 object, the most-derived type of *this will be Person, not Employee2 (it won't become Employee2 until execution enters the Employee2 constructor).
More or less, I have somewhere working like that :
#include <iostream>
#include <functional>
#include <vector>
struct ClassEntry {
size_t id = 0;
const char* label;
};
class BaseClass {
public:
protected:
static void RegisterType(size_t id, const char * label) {
ClassEntry entry;
entry.id = id;
entry.label = label;
mRegisteredTypes.emplace_back(entry);
std::cout << "Registered type " << id << " label " << label << std::endl;
}
static size_t createId() {
static size_t id = 0;
return id++;
}
static std::vector<ClassEntry> mRegisteredTypes;
};
std::vector<ClassEntry> BaseClass::mRegisteredTypes;
class OneTimeCall {
public:
OneTimeCall(std::function<void(void)>&& func) {
func();
}
virtual ~OneTimeCall() {
}
};
template<typename T>
class MyClass : public BaseClass {
public:
MyClass() {
static OneTimeCall one_time {
[this]{
BaseClass::RegisterType(GetId(), T::GetType());
}
};
}
private:
protected:
static size_t GetId() {
static size_t id = BaseClass::createId();
return id;
}
};
class A : public MyClass<A> {
public:
A() {
}
static const char *GetType() {
return "ClassA";
}
};
class B : public MyClass<B> {
public:
B() {
}
static const char *GetType() {
return "ClassB";
}
};
int main() {
A a;
B b;
A a2;
B b2;
return 0;
}
The output is :
Registered type 0 label ClassA
Registered type 1 label ClassB
The main idea is to use CRTP and static initialization in construction for register each type only one time. It works without problems in linux, on windows compiler the static BaseClass ID is new on each DLL, so you need to tune a bit for use in a external library.
With this approach you dont need any external library and is possible to compile without rtti.
For inheritance you can create a new class:
template<typename Current, typename Base>
class Mix : public MyClass<Current>, public Base {};
So if you pass "type C" as current type (CRTP) and type A as base class can work.
class C : public Mix<C, A> {
public:
C() {
}
static const char *GetType() {
return "ClassC";
}
};
With this approach if you have previously registered "A" it will not be registered again, and if you dont have "A" it will be registered after "C".
One way to track objects is to store them an intrusive list and embed a link node into the objects. This provides noexcept guarantee for tracker operations and doesn't require an extra memory allocation when inserting the elements into the tracker container, for the price of an embedded list node (two pointers) in each tracked object:
#include <iostream>
#include <boost/intrusive/list.hpp>
namespace bi = boost::intrusive;
template<class T>
class Tracker : public bi::list_base_hook<bi::link_mode<bi::auto_unlink>>
{
protected:
static bi::list<Tracker, bi::constant_time_size<false>> objects_;
Tracker() noexcept { objects_.push_back(*this); }
Tracker(Tracker const&) noexcept { objects_.push_back(*this); }
public:
static auto count() noexcept { return objects_.size(); }
};
template<class T>
bi::list<Tracker<T>, bi::constant_time_size<false>> Tracker<T>::objects_;
struct Employee : Tracker<Employee> {};
struct Employee2 : Employee {};
int main() {
std::cout << Tracker<Employee>::count() << '\n';
{
Employee e0;
Employee2 e1;
std::cout << Tracker<Employee>::count() << '\n';
}
std::cout << Tracker<Employee>::count() << '\n';
}
Outputs:
0
2
0
Tracker without Boost library:
struct AutoListNode {
AutoListNode *next_ = this, *prev_ = this;
AutoListNode() noexcept = default;
AutoListNode(AutoListNode const&) = delete;
AutoListNode& operator=(AutoListNode const&) = delete;
~AutoListNode() noexcept { this->erase(); }
void push_back(AutoListNode* node) noexcept {
auto prev = prev_;
node->prev_ = prev;
node->next_ = this;
prev->next_ = node;
prev_ = node;
}
void erase() noexcept {
auto next = next_;
auto prev = prev_;
prev->next_ = next;
next->prev_ = prev;
}
size_t size() const noexcept {
size_t count = 0;
for(auto node = next_; node != this; node = node->next_)
++count;
return count;
}
};
template<class T>
class Tracker : private AutoListNode
{
protected:
static AutoListNode objects_;
Tracker() noexcept { objects_.push_back(this); }
Tracker(Tracker const&) noexcept { objects_.push_back(this); }
public:
static auto count() noexcept { return objects_.size(); }
};
template<class T>
AutoListNode Tracker<T>::objects_;

Why does 'visitor pattern' asks each class to inherit VisitorHost interface class which has accept() function?

I am learning a design pattern, vistor pattern, in c++.
At first, I copy my two practice codes below. First one is "my test code", and the second one is a simplified code of "normal visitor pattern" in my text book. I would like you to read the first code but the second one is just a reference code of normal visitor pattern.
My question is why visitor pattern asks each class to inherit VisitorsHostInterface class which has virtual function, accept(); please refer to the second code, "normal visitor pattern", below if necessary. In my understanding, it is not necessary to use accept() function to scan all instances, like the first code, "my test code".
I suppose "my test code" is simpler than "normal visitor pattern".
Please tell me the reason why visitor pattern asks accept() function to each class? Thank you very much.
(1) my test code
class ClassD;
class ClassC {
public:
ClassC(int new_value, ClassD* new_next_object) : value_(new_value), next_object_(new_next_object) {};
void print() { std::cout << "ClassC value_ = " << value_ << std::endl; }
int value() { return value_; }
std::shared_ptr<ClassD> next_object(void) { return next_object_; }
private:
int value_=0;
std::shared_ptr<ClassD> next_object_;
};
class ClassD {
public:
ClassD(int new_value, ClassC* new_next_object) : value_(new_value), next_object_(new_next_object) {};
void print() { std::cout << "ClassD value_ = " << value_ << std::endl; }
int value() { return value_; }
std::shared_ptr<ClassC> next_object(void) { return next_object_; }
private:
int value_=0;
std::shared_ptr<ClassC> next_object_;
};
class VisitorFuncInterface {
public:
virtual ~VisitorFuncInterface() = default;
virtual void visit(ClassC* obj) = 0;
virtual void visit(ClassD* obj) = 0;
};
class VisitorFunc : public VisitorFuncInterface {
public:
virtual ~VisitorFunc() = default;
void visit(ClassC* obj) {
if (obj) {
obj->print();
this->visit(obj->next_object().get());
}
}
void visit(ClassD* obj) {
if (obj) {
obj->print();
this->visit(obj->next_object().get());
}
}
};
void test_visitor_without_host(void) {
ClassD* d0 = new ClassD(0, nullptr);
ClassC* c0 = new ClassC(1, d0);
ClassD* d1 = new ClassD(2, c0);
VisitorFunc v;
v.visit(d1);
delete d1;
}
The result of test_visitor_without_host() is following,
ClassD value_ = 2
ClassC value_ = 1
ClassD value_ = 0
(2) normal visitor pattern code
class ClassA;
class ClassB;
class VisitorInterface {
public:
virtual ~VisitorInterface() = default;
virtual void visit(ClassA* obj) = 0;
virtual void visit(ClassB* obj) = 0;
};
class VisitorsHostInterface { // = visitor's host
public:
virtual ~VisitorsHostInterface() = default;
virtual void accept(VisitorInterface& v) = 0;
};
class VisitorsHost : public VisitorsHostInterface {
public:
virtual ~VisitorsHost();
void accept(VisitorInterface& v) {};
};
class ClassA : public VisitorsHostInterface {
public:
ClassA(int new_value, ClassB* new_next_object) : value_(new_value), next_object_(new_next_object) {};
void print() { std::cout << "ClassA value_ = " << value_ << std::endl; }
int value() { return value_; }
std::shared_ptr<ClassB> next_object(void) { return next_object_; }
void accept(VisitorInterface& v) { v.visit(this); };
private:
int value_=0;
std::shared_ptr<ClassB> next_object_;
};
class ClassB : public VisitorsHostInterface {
public:
ClassB(int new_value, ClassA* new_next_object) : value_(new_value), next_object_(new_next_object) {};
void print() { std::cout << "ClassB value_ = " << value_ << std::endl; }
int value() { return value_; }
std::shared_ptr<ClassA> next_object(void) { return next_object_; }
void accept(VisitorInterface& v) { v.visit(this); };
private:
int value_=0;
std::shared_ptr<ClassA> next_object_;
};
class Visitor : public VisitorInterface {
public:
virtual ~Visitor() = default;
void visit(ClassA* obj) {
if (obj) {
obj->print();
this->visit(obj->next_object().get());
}
}
void visit(ClassB* obj) {
if (obj) {
obj->print();
this->visit(obj->next_object().get());
}
}
};
void test_visitor(void) {
ClassB* b0 = new ClassB(0, nullptr);
ClassA* a0 = new ClassA(1, b0);
ClassB* b1 = new ClassB(2, a0);
Visitor v;
b1->accept(v);
delete b1;
}
The result of test_visitor() is following,
ClassB value_ = 2
ClassA value_ = 1
ClassB value_ = 0
In your example, you hold all the objects by value and know their static & dynamic type. You don't need dynamic dispatch, so you don't need to have a common VisitorsHostInterface base class. All that's required is for your classes to implement an accept function.
However, the visitor pattern is most commonly used when you don't have access to the dynamic type of the visited objects. Say you have a vecotr<unique_ptr<Widget>>. Where many different Widget sub-types are stored by pointer. Than Widget and every one of its sub classes must implement a virtual accept function. To get to the objects dynamic type, you need to do dynamic dispatch.

How can one design a base class, so it knows about all the "derived" classes, at run time?

Normally, if you know all the types you intend to create before hand, you can just do something like this:
typedef enum{
BASE_CREATURE_TYPE = 0,
ANIMAL_CREATURE_TYPE,
...
}CREATURE_TYPES
But this becomes tedious, because each time you create a new class, you need to update the enum. Also, the CREATURE_TYPES is still just items in an enum - how to tie to an actual class ?
I was wondering if there was some way, I could just write the classes, and at run time, without actually instantiating an object, create a set containing all the types.
Is this possible in C++? In Java there is something called "static blocks", which are executed when the class is loaded by the JVM.
EDIT: This question is not about static blocks - It is just an example - I am wondering if there is some way, that I can execute a method or block of code so I know what classes exist at runtime, without actually creating an object
EDIT: I meant set of all types, not "maps", so I can create an object of each type, without having to maintain a list.
EDIT: The reason I want this, is because I am trying to create a function that can call methods on all derived classes that are part of the application. For example, say I have several classes which all derive from class Foo, and have a balls():
Foo{
balls();
}
Boo : public Foo{
balls();
}
Coo: public Foo{
balls():
}
At run time, I would like to know about all the derived classes so I can call:
DerivedClass:balls();
EDIT: Note, that I do not need to know about all the members of each derived class, I just want to know what all the derived classes are, so I can call balls(), on each of them.
EDIT: This question is similar: How to automatically register a class on creation
But unfortunately, he is storing an std::string(). How does one refer to the actual class ?
EDIT: In Smeehey's answer below, in the main method, how would I actually create an instance of each class, and call both static and non-static methods ?
You could create a static registry for all your classes, and use a couple of helper macros to register new types within it. Below is a basic working demonstration, which creates 2 derived classes from Base. To add new classes you just use the two macros shown - one inside and one outside the class. Note: the example is very bare-bones and doesn't concern itself with things like checking for duplicates or other error conditions to maximise clarity.
class BaseClass
{
};
class Registry
{
public:
static void registerClass(const std::string& name, BaseClass* prototype)
{
registry[name] = prototype;
}
static const std::map<std::string, BaseClass*>& getRegistry() { return registry; };
private:
static std::map<std::string, BaseClass*> registry;
};
std::map<std::string, BaseClass*> Registry::registry;
#define REGISTER_CLASS(ClassType) static int initProtoType() { static ClassType proto; Registry::registerClass(std::string(#ClassType), &proto); return 0; } static const int regToken;
#define DEFINE_REG_CLASS(ClassType) const int ClassType::regToken = ClassType::initProtoType();
class Instance : public BaseClass
{
REGISTER_CLASS(Instance)
};
DEFINE_REG_CLASS(Instance)
class OtherInstance : public BaseClass
{
REGISTER_CLASS(OtherInstance)
};
DEFINE_REG_CLASS(OtherInstance)
int main()
{
for(auto entry : Registry::getRegistry())
{
std::cout << entry.first << std::endl;
}
return 0;
}
The above registers prototypes of the derived classes, which could be used for copy-constructing other instances for example. As an alternative, requested by the OP, you can have a system where factory methods are registered instead of prototypes. This allows you to create instances using a constructor with any particular signature, rather than the copy constructor:
class BaseClass
{
};
class Registry
{
public:
using factoryMethod = BaseClass* (*)(int a, int b, int c);
static void registerClass(const std::string& name, factoryMethod meth)
{
registry[name] = meth;
}
static BaseClass* createInstance(const std::string& type, int a, int b, int c)
{
return registry[type](a, b, c);
}
static const std::map<std::string, factoryMethod>& getRegistry() { return registry; };
private:
static std::map<std::string, factoryMethod> registry;
};
std::map<std::string, Registry::factoryMethod> Registry::registry;
#define REGISTER_CLASS(ClassType) static BaseClass* createInstance(int a, int b, int c) \
{ \
return new ClassType(a,b,c); \
} \
static int initRegistry() \
{ \
Registry::registerClass( \
std::string(#ClassType), \
ClassType::createInstance); \
return 0; \
} \
static const int regToken; \
#define DEFINE_REG_CLASS(ClassType) const int ClassType::regToken = ClassType::initRegistry();
class Instance : public BaseClass
{
Instance(int a, int b, int c){}
REGISTER_CLASS(Instance)
};
DEFINE_REG_CLASS(Instance)
class OtherInstance : public BaseClass
{
OtherInstance(int a, int b, int c){}
REGISTER_CLASS(OtherInstance)
};
DEFINE_REG_CLASS(OtherInstance)
int main()
{
std::vector<BaseClass*> objects;
for(auto entry : Registry::getRegistry())
{
std::cout << entry.first << std::endl;
objects.push_back(Registry::createInstance(entry.first, 1, 2, 3));
}
return 0;
}
Use the CRTP design with interface for common "ancestor":
#include <vector>
#include <iostream>
/* Base */
struct IBase
{
virtual void balls() = 0;
virtual IBase *clone() const = 0;
private:
static std::vector<IBase const *> _Derived;
public:
static void
create_all(void)
{
std::cout << "size: " << _Derived.size() << "\n";
for (IBase const *a : _Derived)
{
IBase *new_object(a->clone());
(void)new_object; // do something with it
}
}
};
std::vector<IBase const *> IBase::_Derived;
/* Template for CRTP */
template<class DERIVED>
class Base : public IBase
{
static bool created;
static Base const *_model;
public:
Base(void)
{
if (not created)
{
_Derived.push_back(this);
created = true;
}
}
};
template<class DERIVED>
bool Base<DERIVED>::created = false;
template<class DERIVED>
Base<DERIVED> const *Base<DERIVED>::_model = new DERIVED;
/* Specialized classes */
struct Foo1 : public Base<Foo1>
{
IBase *clone() const
{
std::cout << "new Foo1\n";
return new Foo1(*this);
}
void balls() {}
};
struct Foo2 : public Base<Foo2>
{
IBase *clone() const
{
std::cout << "new Foo2\n";
return new Foo2(*this);
}
void balls() {}
};
int main(void)
{
Foo1 a;
IBase::create_all();
}
I tried this solution, but I do not know why the static Base const *_model; is not created when running the program.
You may use a global factory holding functions able to create objects (unique_ptr's) of derived classes:
#include <memory>
#include <unordered_map>
#include <typeinfo>
#include <typeindex>
// Factory
// =======
template <typename Base>
class Factory
{
public:
template <typename Derived>
struct Initializer {
Initializer() {
Factory::instance().register_producer<Derived>();
}
};
typedef std::function<std::unique_ptr<Base>()> producer_function;
typedef std::unordered_map<std::type_index, producer_function> producer_functions;
static Factory& instance();
void register_producer(const std::type_info& type, producer_function producer) {
m_producers[std::type_index(type)] = std::move(producer);
}
template <typename Derived>
void register_producer() {
register_producer(
typeid(Derived),
[] () { return std::make_unique<Derived>(); });
}
producer_function producer(const std::type_info& type) const {
auto kv = m_producers.find(std::type_index(type));
if(kv != m_producers.end())
return kv->second;
return producer_function();
}
const producer_functions producers() const { return m_producers; }
private:
producer_functions m_producers;
};
template <typename Base>
Factory<Base>& Factory<Base>::instance() {
static Factory result;
return result;
}
// Test
// ====
#include <iostream>
class Base
{
public:
~Base() {}
virtual void print() = 0;
};
class A : public Base
{
public:
void print() override { std::cout << "A\n"; }
static void f() {}
};
Factory<Base>::Initializer<A> A_initializer;
class B : public Base
{
public:
void print() override { std::cout << "B\n"; }
};
Factory<Base>::Initializer<B> B_initializer;
class C {};
int main()
{
auto& factory = Factory<Base>::instance();
// unique_ptr
auto producerA = factory.producer(typeid(A));
if(producerA) {
auto ptrA = producerA();
ptrA->print();
}
// shared_ptr
auto producerB = factory.producer(typeid(B));
if(producerB) {
std::shared_ptr<Base> ptrB(producerB());
ptrB->print();
}
// missing
auto producerC = factory.producer(typeid(C));
if( ! producerC) {
std::cout << "No producer for C\n";
}
// unordered
for(const auto& kv : factory.producers()) {
kv.second()->print();
}
}
Note: The factory does not provide means of calling static member functions without object.

Recursive Template idiom how to avoid that the base class is friend of the child classes

I use the recursive template idiom to automatically register all children of a base class in a factory. However in my design the child class must have as a friend class the base class. As the Constructor of my Base class should be private to avoid instantiation of this class other than via the factory.
The overal aim would be that the registration of the factory is done in the BaseSolver and the ChildClasses cannot be instantiated other than via the factory.
Here is the code of my base class which automatically registers all children in the SolverFactory.
template<class T>
struct BaseSolver: AbstractSolver
{
protected:
BaseSolver()
{
reg=reg;//force specialization
}
virtual ~BaseSolver(){}
/**
* create Static constructor.
*/
static AbstractSolver* create()
{
return new T;
}
static bool reg;
/**
* init Registers the class in the Solver Factory
*/
static bool init()
{
SolverFactory::instance().registerType(T::name, BaseSolver::create);
return true;
}
};
template<class T>
bool BaseSolver<T>::reg = BaseSolver<T>::init();
And here the header file of my child class:
class SolverD2Q5 : public BaseSolver<SolverD2Q5>{
private:
//how can I avoid this?
friend class BaseSolver;
SolverD2Q5();
static const std::string name;
}
This works fine. However I really do not like to have to add the BaseSolver as a friend class, however I do not want the constructor and the static member name to be public.
Is there a more elegant solution or a better layout to avoid this?
UPDATE:
I believe the trick has not been understood hence I created the complete solution now. It is just one little change to the code of the OP. Just replace T in the BaseSolver with an empty class definition deriving from T.
Original Text:
I think you can do it by delegating the friendship to a wrapper class that is private to the base Solver. This class will inherit from any class for which instances are to be created. The compiler should optimize the wrapper class away.
#include <iostream>
#include <map>
struct AbstractSolver { virtual double solve() = 0; };
class SolverFactory
{
std::map<char const * const, AbstractSolver * (*)()> creators;
std::map<char const * const, AbstractSolver *> solvers;
public:
static SolverFactory & instance()
{
static SolverFactory x;
return x;
}
void registerType(char const * const name, AbstractSolver *(*create)())
{
creators[name] = create;
}
AbstractSolver * getSolver(char const * const name)
{
auto x = solvers.find(name);
if (x == solvers.end())
{
auto solver = creators[name]();
solvers[name] = solver;
return solver;
}
else
{
return x->second;
}
}
};
template<class T> class BaseSolver : public AbstractSolver
{
struct Wrapper : public T { // This wrapper makes the difference
static char const * const get_name() { return T::name; }
};
protected:
static bool reg;
BaseSolver() {
reg = reg;
}
virtual ~BaseSolver() {}
static T * create() {
return new Wrapper; // Instantiating wrapper instead of T
}
static bool init()
{
SolverFactory::instance().registerType(Wrapper::get_name(), (AbstractSolver * (*)())BaseSolver::create);
return true;
}
};
template<class T>
bool BaseSolver<T>::reg = BaseSolver<T>::init();
struct SolverD2Q5 : public BaseSolver<SolverD2Q5>
{
public:
double solve() { return 1.1; }
protected:
SolverD2Q5() {} // replaced private with protected
static char const * const name;
};
char const * const SolverD2Q5::name = "SolverD2Q5";
struct SolverX : public BaseSolver<SolverX>
{
public:
double solve() { return 2.2; }
protected:
SolverX() {} // replaced private with protected
static char const * const name;
};
char const * const SolverX::name = "SolverX";
int main()
{
std::cout << SolverFactory::instance().getSolver("SolverD2Q5")->solve() << std::endl;
std::cout << SolverFactory::instance().getSolver("SolverX")->solve() << std::endl;
std::cout << SolverFactory::instance().getSolver("SolverD2Q5")->solve() << std::endl;
std::cout << SolverFactory::instance().getSolver("SolverX")->solve() << std::endl;
char x;
std::cin >> x;
return 0;
}

C++ unique static id and class name with base class

Having class TaskBase, each derived class of it must have name and unique id.
The TaskBase is something like below:
class TaskBase
{
public:
static const int id()
{
// return an unique id, for each object or derived class, HOW ??
}
static const string name()
{
// return class name for each derived class, HOW ??
// for example : "TaskBase" for this class
}
};
My try was :
template <typename DERIVED>
class TaskBase
{
public:
static const int id()
{
static const int id = reinterpret_cast<int> (typeid (DERIVED).name());
return id;
}
static const string name()
{
static string n;
if (!n.size())
{
int status;
char *realname = abi::__cxa_demangle(typeid (DERIVED).name(), 0, 0, &status);
n = realname;
free(realname);
}
return n;
}
};
I already read this, but i need the ability to have base pointer to each derived classes, something line below:
class MyTask1 : public TaskBase
{
};
MyTask1 myTask1, myTask2;
TaskBase *base = &myTask1;
class TaskBase
{
private:
const void* m_id;
string m_name;
public:
TaskBase(const void* m_id, string m_name): m_id(m_id), m_name(m_name)
{
}
const void* id() const
{
return m_id;
}
string name() const
{
return m_name;
};
};
template< typename DERIVED >
class TaskProxy: public TaskBase
{
public:
static const void* id()
{
//if you want to have for each object a unique id:
//return reinterpret_cast<void*>(this);
//just for each TaskProxy<????>:
return reinterpret_cast<const void*>(typeid( DERIVED ).name());
}
static string name()
{
return typeid( DERIVED ).name();
}
TaskProxy(): TaskBase(id(), name()) {}
};
Usage:
class MyTask1 : public TaskProxy< MyTask1 >
{
};
class MyTask2 : public TaskProxy< MyTask2 >
{
};
...
MyTask1 myTask1;
TaskBase *baseA = &myTask1;
MyTask2 myTask2;
TaskBase *baseB = &myTask2;
cout << "Name: " << baseA->name() << " Id:" << baseA->id() << endl;
cout << "Name: " << baseB->name() << " Id:" << baseB->id() << endl;
Which outputs this (with gcc 4.6):
Name: 7MyTask1 Id:0x401228
Name: 7MyTask2 Id:0x4011c0
I suggest implementing pure virtual methods for obtaining the class name and ID in the base class. The descendants would need to provide the unique names and IDs.
class TaskBase
{
public:
virtual std::string get_task_name(void) const = 0;
virtual unsigned long get_task_id(void) const = 0;
};
I took #VoidStar's suggest a step further and put the names into a (single) common class:
class TaskNames
{
protected:
static std::string get_tas1_name();
};
class Task1: public TaskBase, public TaskNames
{
//...
};
If you are following strictly standard C++, you may need to just bite the bullet and do some additional bookkeeping. Make an enum somewhere that stores all the classnames:
enum ClassID {
MYTASK1_CLASS,
MYTASK2_CLASS
};
It doesn't take that long to add a new classId when you make a new class.
I've done this before. It's sufficient for uniqueness to do what I describe above. But... if the enum values are set with a clever enough macro, you can encode the hierarchy of the classes, and implement dynamic cast and instanceof solely from the ClassID and a bitwise mask!