Basically, I want to automatically register object creator functions with an object factory for a bunch of classes defined across many header files.
The top answer to this post, provides a solution -- but it doesn't fit my constraints.
I'm working on an existing code base. For the classes I need to register, there is already a macro following the class declarations that takes the class as a parameter. If I were able to extend the existing macro definition to also do registration, then it would save a lot time because no existing code would have to be changed.
The closest solution I've been able to come up with is creating a macro that defines a template specialization of a method that registers that object, then calls the previously defined template specialization method -- thus chaining all the register calls. Then, when I want to register all classes, I just call the most recently defined specialization and it registers everything in reverse order of #include appearance.
Below, I've posted a simple working example that shows my solution thus far.
The only caveat is that I have no way of automatically keeping track of the last registered type to call in the chain. So I keep redefining the #define LAST_CHAIN_LINK to be the most recently specialized typename. This means that I'd have to add two lines of #undef/#define after every existing macro call -- I'd really like to avoid that.
The main question:
In the code below, is there any way to define the REGISTER_CHAIN macro to work without using the LAST_CHAIN_LINK #undef/#define code too?
If only it were possible to redefine the LAST_CHAIN_LINK token inside the REGISTER_CHAIN method...
My guess is some solution is possible using the __COUNTER__ preprocessor feature, but that is not available on one of the target platforms (OS X using gcc 4.2.x) and thus not an option.
Simplified example (compiles on GNU C++ 4.4.3):
#include <map>
#include <string>
#include <iostream>
struct Object{ virtual ~Object() {} }; // base type for all objects
// provide a simple create function to derived classes
template<class T> struct ObjectT : public Object {
static Object* create() { return new T(); }
};
struct ObjectFactory {
// pass in creator function pointer to register it to id
static Object* create(const std::string& id, Object* (*creator)() = 0) {
static std::map<std::string, Object* (*)()> creators;
return creator && (creators[id] = creator) ? 0 : creators.find(id) != creators.end() ? (*creators.find(id)->second)() : 0;
}
template<class T = int> struct Register { static void chain() {} };
};
#define LAST_CHAIN_LINK // empty to start
#define REGISTER_CHAIN(T) \
template<> void ObjectFactory::Register<T>::chain() \
{ \
ObjectFactory::create(#T, T::create); \
std::cout << "Register<" << #T << ">::chain()\n"; \
ObjectFactory::Register<LAST_CHAIN_LINK>::chain(); \
}
struct DerivedA : public ObjectT<DerivedA> { DerivedA() { std::cout << "DerivedA constructor\n"; } };
REGISTER_CHAIN(DerivedA);
// Can these next two lines be eliminated or folded into REGISTER_CHAIN?
#undef LAST_CHAIN_LINK
#define LAST_CHAIN_LINK DerivedA
struct DerivedB : public ObjectT<DerivedB> { DerivedB() { std::cout << "DerivedB constructor\n"; } };
REGISTER_CHAIN(DerivedB);
// Can these next two lines be eliminated or folded into REGISTER_CHAIN?
#undef LAST_CHAIN_LINK
#define LAST_CHAIN_LINK DerivedB
struct DerivedC : public ObjectT<DerivedC> { DerivedC() { std::cout << "DerivedC constructor\n"; } };
REGISTER_CHAIN(DerivedC);
// Can these next two lines be eliminated or folded into REGISTER_CHAIN?
#undef LAST_CHAIN_LINK
#define LAST_CHAIN_LINK DerivedC
struct DerivedD : public ObjectT<DerivedD> { DerivedD() { std::cout << "DerivedD constructor\n"; } };
REGISTER_CHAIN(DerivedD);
// Can these next two lines be eliminated or folded into REGISTER_CHAIN?
#undef LAST_CHAIN_LINK
#define LAST_CHAIN_LINK DerivedD
int main(void)
{
// Call last link in the register chain to register all object creators
ObjectFactory::Register<LAST_CHAIN_LINK>::chain();
delete ObjectFactory::create("DerivedA");
delete ObjectFactory::create("DerivedB");
delete ObjectFactory::create("DerivedC");
delete ObjectFactory::create("DerivedD");
return 0;
}
example output:
> g++ example.cpp && ./a.out
Register<DerivedD>::chain()
Register<DerivedC>::chain()
Register<DerivedB>::chain()
Register<DerivedA>::chain()
DerivedA constructor
DerivedB constructor
DerivedC constructor
DerivedD constructor
I find your concept pretty complicated and I'm not sure if it's required. From my point of view your problem can be circumvented when adding the following code:
#include <iostream>
#include <map>
#include <string>
struct Object{}; // Value Object
// provide a simple create function to derived classes
template<class T> struct ObjectT : public Object {
static Object* create() { return new T(); }
};
struct ObjectFactory {
std::map<std::string, Object* (*)()> creators_factory;
static ObjectFactory* instance()
{
static ObjectFactory* __self = NULL;
if (__self == NULL)
__self = new ObjectFactory();
return __self;
}
template <class T> bool reg(const std::string& id, Object* (*creator)() )
{
creators_factory[id] = creator;
return true;
}
// pass in creator function pointer to register it to id
static Object* create(const std::string& id) {
return instance()->creators_factory[id]();
}
};
#define REGISTER_CHAIN(T) bool isRegistered_##T = ObjectFactory::instance()->reg<T>(#T, T::create)
struct DerivedA : public ObjectT<DerivedA> { DerivedA() { std::cout << "DerivedA constructor\n"; } };
REGISTER_CHAIN(DerivedA);
struct DerivedB : public ObjectT<DerivedB> { DerivedB() { std::cout << "DerivedB constructor\n"; } };
REGISTER_CHAIN(DerivedB);
struct DerivedC : public ObjectT<DerivedC> { DerivedC() { std::cout << "DerivedC constructor\n"; } };
REGISTER_CHAIN(DerivedC);
struct DerivedD : public ObjectT<DerivedD> { DerivedD() { std::cout << "DerivedD constructor\n"; } };
REGISTER_CHAIN(DerivedD);
int main(void)
{
// Call last link in the register chain to register all object creators
//ObjectFactory::Register<LAST_CHAIN_LINK>::chain();
delete ObjectFactory::create("DerivedA");
delete ObjectFactory::create("DerivedB");
delete ObjectFactory::create("DerivedC");
delete ObjectFactory::create("DerivedD");
return 0;
}
I hope this helps.
Best regards,
Martin
Using Martin/ #grundprinzip 's suggestion I've been able to solve my problem. I had to modify his approach a bit to allow registration of classes in namespaces.
Thanks Martin!
But, I have a follow-up question now: Isn't it possible the that compiler will entirely optimize out the static ObjectFactory::Register::creator variable (equivalent to is_Registered_##T in #grundprinzip 's code) -- because no code actually references this value?
If so, then optimizing out the variable will optimize out the initialization...thus breaking what I'm hoping to achieve.
Here is the revised code:
#include <map>
#include <string>
#include <iostream>
struct Object{ virtual ~Object() {} }; // base type for all objects
struct ObjectFactory {
static Object* create(const std::string& id) { // creates an object from a string
const Creators_t::const_iterator iter = static_creators().find(id);
return iter == static_creators().end() ? 0 : (*iter->second)(); // if found, execute the creator function pointer
}
private:
typedef Object* Creator_t(); // function pointer to create Object
typedef std::map<std::string, Creator_t*> Creators_t; // map from id to creator
static Creators_t& static_creators() { static Creators_t s_creators; return s_creators; } // static instance of map
template<class T = int> struct Register {
static Object* create() { return new T(); };
static Creator_t* init_creator(const std::string& id) { return static_creators()[id] = create; }
static Creator_t* creator;
};
};
#define REGISTER_TYPE(T, STR) template<> ObjectFactory::Creator_t* ObjectFactory::Register<T>::creator = ObjectFactory::Register<T>::init_creator(STR)
namespace A { struct DerivedA : public Object { DerivedA() { std::cout << "A::DerivedA constructor\n"; } }; }
REGISTER_TYPE(A::DerivedA, "A");
namespace B { struct DerivedB : public Object { DerivedB() { std::cout << "B::DerivedB constructor\n"; } }; }
REGISTER_TYPE(B::DerivedB, "Bee");
namespace C { struct DerivedC : public Object { DerivedC() { std::cout << "C::DerivedC constructor\n"; } }; }
REGISTER_TYPE(C::DerivedC, "sea");
namespace D { struct DerivedD : public Object { DerivedD() { std::cout << "D::DerivedD constructor\n"; } }; }
REGISTER_TYPE(D::DerivedD, "DEE");
int main(void)
{
delete ObjectFactory::create("A");
delete ObjectFactory::create("Bee");
delete ObjectFactory::create("sea");
delete ObjectFactory::create("DEE");
return 0;
}
produces the correct result:
> g++ example2.cpp && ./a.out
A::DerivedA constructor
B::DerivedB constructor
C::DerivedC constructor
D::DerivedD constructor
Related
I want to create objects with polymorphic types based on a string I read from some config text file. A naive simple solution to this is to assign a string to each possible type and then compare the config string in an else-if chain to all the defined types. Something like:
class Base
{
virtual std::string GetStringType() = 0;
};
class Derived1 : public Base
{
std::string GetStringType() override { return "Derived1"; }
};
class Derived2 : public Base
{
std::string GetStringType() override { return "Derived2"; }
};
// etc ...
void main(int argc, char *argv[])
{
std::unique_ptr<Base> ptr;
auto derived1 = std::make_unique<Derived1>();
auto derived2 = std::make_unique<Derived2>();
// etc ...
std::string stringType(argv[1]);
if (stringType == derived1->GetStringType())
ptr = std::make_unique<decltype(derived1)>();
else if (stringType == derived2->GetStringType())
ptr = std::make_unique<decltype(derived2)>();
// etc ...
}
However, with this approach, each time a new derived class is added, a new else-if branch needs to be manually added, and I am trying to avoid that. Is there a better, more automatic approach to this?
Also, in an ideal scenario, when a new derived class is defined somewhere (just defined, not instantiated), I would like to check against it automatically also. Is this somehow possible? I'd be happy for any solution that works, macros included.
A simple map-based factory can do the trick:
#include <map>
#include <functional>
#include <string>
#include <memory>
class Base
{
public:
virtual ~Base() = default;
static std::unique_ptr<Base> create(const std::string& name) {
return factories_.at(name)();
}
template<typename T>
static void registerDerived() {
static_assert(std::is_base_of_v<Base, T>);
factories_[T::GetStringType()] = std::make_unique<T>;
}
private:
static std::map<std::string, std::function<std::unique_ptr<Base>()>> factories_;
};
std::map<std::string, std::function<std::unique_ptr<Base>()>> Base::factories_;
class Derived1 : public Base
{
public:
static std::string GetStringType() { return "Derived1"; }
};
class Derived2 : public Base
{
public:
static std::string GetStringType() { return "Derived2"; }
};
int main(int argc, char *argv[]) {
Base::registerDerived<Derived1>();
Base::registerDerived<Derived2>();
// etc...
std::unique_ptr<Base> ptr = Base::create(argv[1]);
// ...
}
This is an example based on unordered_map, with an explicit class factory.
Decoupling the creation of the instances completely from the base class.
(Separation of concerns)
#include <type_traits>
#include <string>
#include <functional>
#include <iostream>
#include <memory>
#include <unordered_map>
#include <stdexcept>
#include <sstream>
//-------------------------------------------------------------------------------------------------
class Base
{
public:
virtual void Hello() = 0;
};
class Class1 : public Base
{
public:
void Hello() override
{
std::cout << "Class1\n";
}
};
class Class2 : public Base
{
public:
void Hello() override
{
std::cout << "Class2\n";
}
};
//-------------------------------------------------------------------------------------------------
class ClassFactory final
{
public:
// For each class registered at a function to the map
// that will create a unique_ptr to a new instance of that class
template<typename class_t>
void Register(const std::string& string)
{
static_assert(std::is_base_of_v<Base, class_t>, "You can only register classes derived from Base");
// create_function is a lambda
auto create_function = [] { return std::make_unique<class_t>(); };
// add the function to the map, with the string as key
create_function_map.insert({ string,create_function });
}
std::unique_ptr<Base> Create(const std::string& string)
{
// if nothing is found for the string then throw an exception
if (create_function_map.find(string) == create_function_map.end())
{
std::ostringstream os;
os << "No class registered for string : " << string;
throw std::invalid_argument(os.str());
}
// otherwise call the function that will make an instance of the
// derived class
auto create_function = create_function_map.at(string);
return create_function();
}
static ClassFactory& Instance()
{
static ClassFactory instance;
return instance;
}
private:
ClassFactory() = default;
~ClassFactory() = default;
// use unordered_map it has lookup complexity of O(1)
// std::map has a lookup complexity of O(n log(n))
std::unordered_map<std::string, std::function<std::unique_ptr<Base>()>> create_function_map;
};
//-------------------------------------------------------------------------------------------------
int main()
{
// For each new class register a name, this is the only code
// you need to expand to add new classes
// factory is a singleton so you can reuse it throughout your code
// without having to pass it around.
auto& factory = ClassFactory::Instance();
factory.Register<Class1>("Class1");
factory.Register<Class2>("Class2");
// create an instance of an object of type Class1.
auto object1 = factory.Create("Class1");
object1->Hello();
// create an instance of an object of type Class2.
auto object2 = factory.Create("Class2");
object2->Hello();
return 0;
}
Suppose we have a base class and a bunch of derived classes. Is there any way or mechanism to know all the derived class names programmatically?
Maybe reflection is a good idea, but it's not available on C++. I suppose there will be some kind of template that can finish this job during compilation.
class Base{
public:
virtual void print(){
// This function should print all the names of derived class.
}
virtual Base* getInstance(string class_name){
// This function should return an instance related to the class name.
}
};
class Derived_1 : public Base{ // Suppose we have 100 Derived_X classes,
// so we don't want to add its name to a list manually.
};
int main(){
Base base;
base.print(); // This should print the name of all the derived class.
base.getInstance("Derived_1"); // This should return an instance of Derived_1
return 0;
}
This solution is based on the fact that it seems you are actually looking for a factory. It uses a small macro to ease classes registration, hope you don't care about it.
factory.h
#ifndef __FACTORY_H__
#define __FACTORY_H__
#include <map>
#include <functional>
#include <string>
#include <iostream>
template<class B>
class Factory {
std::map<std::string, std::function<B*()>> s_creators;
public:
static Factory<B>& getInstance() {
static Factory<B> s_instance;
return s_instance;
}
template<class T>
void registerClass(const std::string& name) {
s_creators.insert({name, []() -> B* { return new T(); }});
}
B* create(const std::string& name) {
const auto it = s_creators.find(name);
if (it == s_creators.end()) return nullptr; // not a derived class
return (it->second)();
}
void printRegisteredClasses() {
for (const auto &creator : s_creators) {
std::cout << creator.first << '\n';
}
}
};
#define FACTORY(Class) Factory<Class>::getInstance()
template<class B, class T>
class Creator {
public:
explicit Creator(const std::string& name) {
FACTORY(B).registerClass<T>(name);
}
};
#define REGISTER(base_class, derived_class) \
Creator<base_class, derived_class> s_##derived_class##Creator(#derived_class);
#endif
example.cpp
#include "factory.h"
#include <memory>
class Base {
public:
virtual void printName() const { std::cout << "Base\n"; }
};
class Derived1 : public Base {
public:
virtual void printName() const override { std::cout << "Derived1\n"; }
};
REGISTER(Base, Derived1);
class Derived2 : public Base {
public:
virtual void printName() const override { std::cout << "Derived2\n"; }
};
REGISTER(Base, Derived2);
int main() {
std::cout << "Registered classes:" << std::endl;
FACTORY(Base).printRegisteredClasses();
std::cout << "---" << std::endl;
std::unique_ptr<Base> derived1(FACTORY(Base).create("Derived1"));
derived1->printName();
return 0;
}
Note: requires C++11.
For the getInstance you can declare it a template (needs C++14). To get all the names of the derived classes in the program you probably have to resort to some preprocessor hack.
#include <type_traits>
class Base
{
public:
virtual ~Base () = default;
template < typename T,
typename = std::enable_if_t<std::is_base_of<Base, T>::value, void>
>
T getInstance() { return T{}; }
};
class Derived : public Base {};
class NotDerived {};
int main(){
Base base;
base.getInstance<Derived>();
// error: no matching member function for call to 'getInstance'
//base.getInstance<NotDerived>();
}
Regarding the name of the derived classes, I propose a solution based on a BaseList class/struct, with a static std::set (or other container) of names, a template Base class/struct, that inherit from BaseList and whose template parameter is the derived class (CRTP style) and (to semplify the construction of the derived classes/struct, a C-style macro (I know... macros are distilled evil... but sometimes...) to create the declaration of the derived classes/structs with a necessary static method, that declare the name of the derived class/struct, and a member (that activate the registration of the name).
The following is a full example (unfortunately is a C++11 one)
#include <set>
#include <string>
#include <iostream>
struct BaseList
{
static std::set<std::string> const & derList (std::string const & dn)
{
static std::set<std::string> dl;
if ( dn.size() )
dl.insert(dn);
return dl;
}
static void print ()
{
std::cout << "derived names: ";
for ( auto const & dn : derList("") )
std::cout << dn << ", ";
std::cout << std::endl;
}
};
template <typename Der>
struct Base : public BaseList
{
static std::size_t setNameInList ()
{ return derList(Der::name()).size(); }
static std::size_t id;
};
template <typename Der>
std::size_t Base<Der>::id = setNameInList();
#define setDerived(nameDer) \
struct nameDer : public Base<nameDer>\
{ \
std::size_t idc { id }; \
static std::string name () \
{ return #nameDer; }
setDerived(Derived_1)
// other elements
};
setDerived(Derived_2)
// other elements
};
setDerived(Derived_3)
// other elements
};
int main()
{
BaseList::print();
}
Regarding the getInstance() problem, the only solution that I can imagine is the same solution proposed by Enry Menke (+1), so I suggest that you get the instance through a template type parameter.
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.
I'm wondering if there is anyway to do something like this pseudo code:
class A : public std::enable_shared_from_this<A> {
public:
std::shared_ptr<self_t> getPtr(){
return std::static_pointer_cast<self_t>(shared_from_this());
}
};
class B : public A {
std::vector<A> container;
std::shared_ptr<self_t> addChild(A child){
container.push_back(child);
return getPtr();
}
};
class C : public B {
public:
std::shared_ptr<self_t> doSomething(){
// something
return getPtr();
}
};
int main(){
A obja = new A();
C obj = new C();
obj->addChild(obja)->doSomething()
}
My goal is that an object represents a view (as in the V in MVC), and for methods to be able to return itself for chained calling. Eg: ->setTop(0)->addChild(child1)->setBottom(0).
I've read that it may be more approachable to do something like overloading the << operator, but I don't see that working to well or looking very pretty.
One thought I had was to make a macro called VIEW(name,parent) that would use templates to expand out, but I had issue with self-refferental default template arguments.
Any help would be greatly appreciated.
-- edit --
In a nut shell, I'm hoping to have a base class inherit from enable_shared_from_this. The base class would have a method such as doSomething that returns the shared pointer. When a derived class inherits from the base class, I want the doSomething method to return a shared pointer to the derived class. I want to be able to do this without overriding doSomething in the derived class.
This kind of concept would be covered by extension methods which exist outside a class definition, do not violate the class permissions but can be called like a method... which exists in C# but not currently in C++. The code in C# looks like this:
// c# syntax
namespace MyBaseExtensions {
public static class MyBaseExt {
public static shared_ptr<T> getPtr<T>(this T self) where T : MyBase
{
return static_pointer_cast<T>(self.shared_from_this());
}
}
}
This allows for operator chaining because each inheritance of a class line MyBase would have its own definition of the function because the function is not an inherited method but instead applied directly to each related type.
The argument against is that extensions pollute the object with often unneeded functionality and that a standalone template function will do the same thing. The issue is that with that logic:
int main(){
A obja = new A();
C obj = new C();
obj->getPtr()->addChild(obja)->doSomething()
}
ends up looking like
int main(){
A obja = new A();
C obj = new C();
doSomething(addChild(getPtr(obj),obja)); //eyeroll.
}
and you would still be declaring the template functions such like
// C++ syntax
namespace MyBaseExtensions {
template<typename T> std::shared_ptr<T> getPtr<T>(T self)
{
return std::static_pointer_cast<T>(self->shared_from_this());
}
}
As for a simple internal way of applying a template uniquely to each derived type, I am not sure of any. The reason for this is that the functionality you want is not method inheritance but that each future class inherits a template which it automatically specializes(and of which the resulting method is either not inherited or hidden.) For that purpose C++ classes would need to have non-inherited specialized public methods, which are not covered by the current access permissions public, private, and protected or template capabilities.
I would be overjoyed to find a nice way to pull off operator chaining.
And since I have gone and wasted your time I made an attempt at this:
#include <vector>
#include <memory>
// 0 argument, creates an overload method (and hides parent class method)
// from template method func_name
// template method specialization of a parent method does not work
// so we use C++11 automatic type deduction to figure the
// template return type and return what the template returns
#define FUNC_DEF_0(base, cur, func_name) \
auto func_name() \
-> decltype(base().func_name<cur>()) { \
return base::func_name<cur>(); \
}
// 1 argument
#define FUNC_DEF_1(base, cur, func_name, arg1_t) \
auto func_name(arg1_t param1) \
-> decltype(base().func_name<cur>(param1)) { \
return base::func_name<cur>(param1); \
}
// class A
// add to class to hide class A methods
#define HIDE_A(current) \
FUNC_DEF_0(A, current, getPtr)
class A : public std::enable_shared_from_this<A> {
public:
template<typename _T = A>
std::shared_ptr<_T> getPtr(){
return std::static_pointer_cast<_T>(shared_from_this());
}
};
// class B
// add to class to hide class B methods with new methods
#define HIDE_B(current) \
HIDE_A(current) \
FUNC_DEF_1(B, current, addChild, A)
class B : public A {
public:
std::vector<A> container;
template<typename _T = B>
std::shared_ptr<_T> addChild(A child){
container.push_back(child);
return A::getPtr<_T>();
}
HIDE_A(B); // hide A methods with B specialized methods
// Example method hiding
// auto getPtr() -> decltype(A().getPtr<B>()) {
// return base::getPtr<B>();
// }
};
// class C
// add to class to hide class C methods
#define HIDE_C(current) \
HIDE_B(current) \
FUNC_DEF_0(C, current, doSomething)
class C : public B {
public:
template<typename _T = C>
std::shared_ptr<_T> doSomething(){
// something
return A::getPtr<_T>();
}
HIDE_B(C); // hide B methods
};
int main() {
auto obja = std::make_shared<A>();
auto obj = std::make_shared<C>();
obj->addChild(*obja)->doSomething();
}
Edit: Fixed attempt. Compiles for me.
class A;
struct virtual_enable_shared_from_this_base :
std::enable_shared_from_this<virtual_enable_shared_from_this_base> {
virtual ~virtual_enable_shared_from_this_base() {}
};
#define HIDE_AMix(type) \
using type::getPtr;
template<typename _T>
class AMix : public virtual virtual_enable_shared_from_this_base {
public:
std::shared_ptr<_T> getPtr() {
auto sptr = shared_from_this();
return std::dynamic_pointer_cast<_T>(sptr);
}
};
#define HIDE_BMix(type) \
HIDE_AMix(type) \
using type::addChild;
template<typename _T>
class BMix : public AMix<_T>{
public:
std::vector<std::shared_ptr<A>> container;
std::shared_ptr<_T> addChild(A* child){
container.push_back(child->getPtr());
return getPtr();
}
};
#define HIDE_CMix(type) \
HIDE_BMix(type) \
using type::addChild;
template<typename _T>
class CMix : public BMix<_T>{
public:
std::shared_ptr<_T> doSomething(){
// something
return getPtr();
}
};
class A : public AMix<A> {
public:
};
class B : public A, public BMix<B> {
public:
HIDE_AMix(BMix<B>);
//using BMix<B>::getPtr;
//using BMix<B>::addChild;
};
class C : public B, public CMix<C> {
public:
HIDE_BMix(CMix<C>);
//using CMix<C>::getPtr;
//using CMix<C>::addChild;
//using CMix<C>::doSomething;
};
int main() {
auto obja = std::make_shared<B>();
auto obj = std::make_shared<C>();
obja->getPtr();
obj->addChild(obja.get())->doSomething();
}
Edit2: Here is another version from fiddling around with templates.
Here is an example of what you may be trying to accomplish (though I'm not sure I 100% understood your requirements or reasoning for this design). Hope it helps...
#include <iostream>
#include <memory>
#include <vector>
class MyBase;
typedef std::shared_ptr<MyBase> MyBaseSharedPtr;
class MyBase : public std::enable_shared_from_this<MyBase> {
public:
MyBaseSharedPtr getPtr() { return shared_from_this(); }
virtual MyBaseSharedPtr doSomething() { return getPtr(); };
virtual MyBaseSharedPtr addChild(MyBaseSharedPtr child) { return getPtr(); };
};
class MyDerived1 : public MyBase {
private:
std::vector<MyBaseSharedPtr> container;
public:
MyBaseSharedPtr addChild(MyBaseSharedPtr child) {
container.push_back(child);
std::cout << "class MyDerived1: adding child\n";
return getPtr();
};
virtual MyBaseSharedPtr doSomething() {
std::cout << "class MyDerived1: doing something\n";
return getPtr();
}
};
class MyDerived2 : public MyDerived1 {
public:
MyBaseSharedPtr doSomething() {
std::cout << "class MyDerived2: doing something\n";
return getPtr();
}
};
int main(void ) {
MyBaseSharedPtr myBase = std::make_shared<MyBase>();
MyBaseSharedPtr myDerived2 = std::make_shared<MyDerived2>();
myDerived2->addChild(myBase)->doSomething();
return 0;
}
template<typename _T>
shared_ptr<_T> allocate()
{
shared_ptr<_T> ptr(new _T);
// this may need to be changed to
// something like (*typename ptr.get()).weak_this
// if the compiler won't accept a duck-typed _T::weak_this
ptr.get()->weak_this = weak_ptr<_T>(ptr);
return ptr;
}
class A
{
weak_ptr<A> weak_this;
friend shared_ptr<A> allocate<A>();
public:
shared_ptr<A> getPtr(){return weak_this.lock();}
shared_ptr<A> doSomething()
{
// do something
return getPtr();
}
};
Based on your example, if what you really want is to be able to extend functionality without exploding multiple inheritance hierarchies and without overwriting each method everywhere, you could try composed functionality with templates. Something like this:
#include <list>
#include <iostream>
struct Base {
};
template <class Parent>
struct A : Parent {
std::list<Parent*> children;
A* addChild(Parent* child) {
children.push_back(child);
return this;
}
};
template <class Parent>
struct B : Parent {
B* doSomething() {
std::cout << "Something" << std::endl;
return this;
}
};
int main(){
typedef A< B<Base> > Composed;
Composed a;
Composed b;
a.addChild(&b)->doSomething();
}
Note, however, that this has the restriction that forces a use order based on the order you compose the "functionality" (classes).
That is, in this example, you can't do:
a.doSomething()->addChild(&b); //ERROR! B is not a A
But this would work if you declare:
typedef B< A<Base> > Composed; //Note the order of B and A
I don't know if it suits your needs.
Hope this helps, at least, to enable you to think the problem in a different way.
My library uses the Object Factory technique to create "Nodes" that have a specific purpose. By default these Nodes do their job but are quite basic. I want to allow the users of my library to be able and create a sub-class of the provided "Node" class to define their own functionality while keeping the base functionality of a node intact.
Here is some example code to demonstrate my question:
class Node
{
int SomeValue;
public:
Node(int Value)
{
SomeValue = Value;
}
~Node()
{
// Cleanup the node
}
};
class NodeFactory
{
std::vector<Node*> Nodes;
public:
void CreateNode(int Value)
{
Nodes.push_back(new Node(Value));
}
};
This shows the basic Object Factory technique, now for my question.
Can I add a function to the "NodeFactory" such as "void SetType()" and be able to pass in a sub-class of "Node" which in turn will have it create that sub-class during the "CreateNode" function?
Thank you very much for your time it is greatly appreciated.
EDIT:
The usage of "void CreateNode()" is abstracted away from the end user thus my curiosity towards a "void RegisterType()" function where the user can register their sub-class for the factory to create instead of the base-class I provide.
EDIT:
A more concise way to phrase the question would be as follows: How can I let the user tell the factory to create instances of their sub-class, if they've defined one, instead of my default base-class? I want to thank everyone again for their time and effort in answering this question.
I think the problem here is combining the following two requirements:
You want to use the quite simple function void CreateNode(int) to create any node.
You want the user to be able to create new nodes derived from Node and use your factory to create them.
Now what I would suggest is something similar to R Sahu however without following the Factory pattern as strictly as he did.
You could get the functionality you seek by requiring your users to pass a small Creator-object to your factory. (Note that this is deviating a bit from the classical Factory-pattern. As you basically make your NodeFactory into a delegator using the creator-classes.)
class NodeCreator {
public:
virtual Node* create(int) = 0;
virtual ~NodeCreator() = default;
};
class DefaultNodeCreator : public NodeCreator {
public:
virtual Node* create(int value) {
return new Node(value);
}
};
Now I as a user will create my own node:
class MyNode : public Node {
private:
int otherValue;
public:
MyNode(int nodeValue, int otherValue )
: Node(nodeValue), otherValue(otherValue)
{}
// Implement other functionality...
};
class MyNodeCreator : public NodeCreator {
private:
// I added otherNodeValue to show that Creators can have a state.
int otherNodeValue;
public:
MyNodeCreator(int otherNodeValue ) : otherNodeValue(otherNodeValue) {}
virtual Node* create(int value) {
return new MyNode(value, otherNodeValue);
}
};
Now finally in your Factory class you need to set it like this:
class NodeFactory
{
std::vector<Node*> Nodes;
std::unique_ptr<NodeCreator> activeCreator;
public:
NodeFactory() {
setNodeCreator(nullptr);
}
void createNode(int Value)
{
Nodes.push_back( activeCreator->create(Value) );
}
void setNodeCreator( std::unique_ptr<NodeCreator> creator ) {
if (creator == nullptr) {
activeCreator.reset( new DefaultNodeCreator() );
else {
activeCreator.reset(creator);
}
}
};
To use it from main:
int main() {
NodeFactory nf;
nf.createNode(1); // Creating Node(1)
nf.createNode(2); // Creating Node(2)
nf.setCreator( new MyNodeCreator(5) );
// Any nodes created now will be of type MyNode
// with otherNodeValue == 5.
nf.createNode(2); // Creating MyNode(2, 5)
nf.createNode(3); // Creating MyNode(3, 5)
}
A final note:
If you intend for your users to implement subclasses of Node and use these with polymorphism as shown above, it is important that you declare Node's destructor as virtual. You have no guarantee that your users will not use dynamic allocation in their subclasses, so it is your responsibility to ensure that their destructors get called.
A Factory Pattern is meant to create objects with an indirect reference. For example, the user should be able call:
Node* node = Factory::createNode("MyNodeType");
If there is a Factory that can create such a Node, then the function returns with a pointer to a MyNodeType object. Otherwise, it return NULL.
In order for this function to work, a Factory has to be registered that can construct objects of type MyNodeType. We will have to trust that such a Factory creates Nodes of that type.
The classes involved in this patter:
The abstract base class Node.
The abstract base class Factory.
Concrete sub-class of Node called MyNodeType.
Concreate sub-class of Factory. Let's call it MyNodeTypeFactory.
Here's such a skeletal structure.
Node.h:
class Node
{
virtual ~Node() = 0;
};
Factor.h:
#include <string>
class Factory
{
public:
static void registerFactory(std::string const& productType,
Factory* factory);
static Node* creatNode(std::string const& productType);
private:
virtual Node* createNode();
};
Factory.cc:
#include <map>
typedef std::map<std::string, Factory*> FactoryMap;
static FactoryMap& getFactoryMap()
{
static FactoryMap factoryMap;
return factoryMap;
}
static void registerFactory(std::string const& productType,
Factory* factory)
{
getFactoryMap()[productType] = factory;
}
static Node* creatNode(std::string const& productType)
{
FactoryMap& factoryMap = getFactoryMap();
FactoryMap::iterator iter = factoryMap.find(productType);
if ( iter == factoryMap.end() )
{
// Unknown product.
return NULL;
}
return iter->second->createNode();
}
MyNodeType.h:
#include "Node.h"
class MyNodeType : public Node
{
MyNodeType() {}
virtual ~MyNodeType() {}
};
MyNodeTypeFactory.h:
#include <Factory.h>
class MyNodeTypeFactory : public Factory
{
public:
virtual Node* createNode();
};
MyNodeTypeFactory.cc:
#include "MyNodeTypeFactory.h"
struct RegistrationHelper
{
MyNodeTypeFactorHelper()
{
Factory::registerFactory("MyNodeType", new MyNodeTypeFactory());
}
};
static RegistrationHelper helper;
Node* MyNodeTypeFactory::createNode()
{
return MyNodeType();
}
You probably even don't need a RegisterType()... The simplest way is to use C++11 (it allows you to derive nodes w/ different, than a base Node, constructor signatures):
#include <iostream>
#include <memory>
#include <string>
#include <type_traits>
#include <vector>
class Node
{
int SomeValue;
public:
Node(int Value)
: SomeValue{Value}
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
// ATTENTION Make destructor virtual!
virtual ~Node()
{
// Cleanup the node
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
class SomeOtherNode : public Node
{
std::string SomeStringValue;
public:
SomeOtherNode(int Value, const std::string StringValue)
: Node{Value}
, SomeStringValue{StringValue}
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
~SomeOtherNode()
{
// Cleanup the string node
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
class NotARealNode
{
int SomeValue;
public:
NotARealNode(int Value)
: SomeValue{Value}
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
~NotARealNode()
{
// Cleanup the node
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
class NodeFactory
{
std::vector<std::unique_ptr<Node>> Nodes;
public:
template <typename NodeType, typename... Args>
typename std::enable_if<
std::is_base_of<Node, NodeType>::value
>::type CreateNode(Args&&... args)
{
Nodes.push_back(
std::unique_ptr<NodeType>{
new NodeType{std::forward<Args>(args)...}
}
);
}
};
int main()
{
NodeFactory f;
f.CreateNode<Node>(123);
f.CreateNode<SomeOtherNode>(123, "Hello");
#if 0
// ATTENTION It wont compile, cuz NotARealNode is not a child of Node!
f.CreateNode<NotARealNode>(123);
#endif
return 0;
}
Output:
zaufi#gentop>/work/tests> g++ -std=c++11 -o fff fff.cc
zaufi#gentop>/work/tests> ./fff
Node::Node(int)
Node::Node(int)
SomeOtherNode::SomeOtherNode(int, std::string)
virtual Node::~Node()
virtual SomeOtherNode::~SomeOtherNode()
virtual Node::~Node()
You could (should?) use polymorphism for that. Just derive from NodeFactory (make CreateNode a virtual function) and have it spawn Nodes of your desired type. Of course you would have to move the Nodes vector into a different class.