callback function design C++ - c++

I'm trying to implement a callback manager that can register and execute the callbacks from different classes, which each classes are from a different DLL.
Each of these classes derives from a common base class. I know how a single class can make use of a template class like below to register and call its own function, but how can this be applied to use on multiple classes sharing the same callback manager?
Any help will be greatly appreciated.
file: callbacktemplate.h
------------------------
#include <functional>
#include <string>
template <class cInstance>
class cCallBackManager
{
private:
typedef void (cInstance::*tFunction)();
typedef std::map<std::string, tFunction> funcMap;
funcMap i_funcMap;
public:
void SetFunPointer(std::string funcName, tFunction function)
{
i_funcMap.insert(std::pair<std::string, tFunction>(funcName, function));
}
void GetFunPointer(cInstance& obj) //how to call this without knowing the type?
{
for (funcMap::iterator it = i_funcMap.begin();it!=i_funcMap.end(); ++it)
{
(obj.*(it->second))();
}
}
};
file:example.h
---------------
#include "callbacktemplate.h"
class A: public base
{
private:
cCallBackManager<A> callback;
public:
A()
{
callback.SetFunPointer<A>("eventA", &A::testcallback);
callback.GetFunPointer(&this); //how to generalize this so this can be called from the callback manager with the class object?
};
~A(){};
void testCallback();
};
class B: public base
{
private:
cCallBackManager<B> callback;
public:
B()
{
callback.SetFunPointer<B>("eventB", &B::testcallback);
};
~B(){};
void testCallback();
};
file: main.cpp
------------------
#include "derived.h"
int main()
{
A a;
B b;
//create a callback manager to execute the callback?
callbackmgr.execute() //execute all the callback
return 0;
}
lf not using templatized callback manager, how can i achieve something like SetFunPointer(EVENT_NAME, (Base Class)A::testCallback)?

Thanks guys. I've managed to come up with something with your "pointers". :)
File: cCallBackInterface.h
template<class cClass>
class cCallBackInterface
{
public:
cCallBackInterface(){};
~cCallBackInterface(){};
typedef void (cClass::*Function)();
cCallBackInterface(cClass* obj, Function _Function)
{
cInstance = obj;
m_Function = _Function;
}
void execute()
{
(cInstance->*m_Function)();
}
private:
cClass* cInstance;
Function m_Function;
};
File: base.h
class BaseModel;
typedef cCallBackInterface<BaseModel> CallBackInterface;
typedef void(BaseModel::*basefn)();
class BaseModel
{
public:
BaseModel(){};
~BaseModel(){};
}
};
class derived : public BaseModel
{
public:
derived(){};
~derived(){};
void dosomething()
{
cout << "derived class is doing something." << endl;
}
};
File: main.cpp
int main()
{
derived a;
std::vector<CallBackInterface> callback;
callback.push_back(CallBackInterface(&a, (basefn)(&derived::Adosomething)));
for(int i = 0; i < callback.size(); i++)
callback[i].execute();
return 0;
}

You can look at this question regarding using member-function pointers.
What it boils down to is that you need the instance as well as the mem-func pointer, you cannot have a generic one to be used anywhere.

Related

How to embeed class in c++ library with main()?

I have c++ library with code following code structure:
#include <vector>
std::vector<Base*> UserClasses;
int main(int argc,char** argv)
{
Init(argc,argv)
while(true)
{
for(auto* class : UserClasses){
class->start();
}
DoStuff();
for(auto* class : UserClasses){
class->update();
}
DoStuff();
}
Shutdown();
}
Base class is interface class with virtual methods.Like this:
class Base
{
public:
Base();
virtual ~Base();
virtual void start() = 0;
virtual void update() = 0;
};
The user will write his own classes like this:
class MyClass : public Base
{
public:
MyClass ();
~MyClass ();
virtual void start() override
{
//userstaff
};
virtual void update() override
{
//userstaff
};
};
I want to allow user to include my library and headers in his project, write his own child classes and compile project into executable.
But how can my library create instance of user classes?
It doesn't know anything about them.
Is it possible somehow create instance of class within header file and push it to vector?
I saw that it can be done by initializing static variables because it happens before main but I don't understand how to implement it.
As properly mentioned in the comments, do not define main in a library. Also, avoid non-const global variables, since this is a bad thing (tm). Instead, define a function and pass UserClasses to it directly. And it is better to encapsulate all the state you have in a class:
class Main {
public:
Main(int argc, char** argv) {
Init(argc, argv);
}
int run(const std::vector<std::unique_ptr<Base>>& user_classes)
{
while(true)
{
for(const auto& class : user_classes){
class->start();
}
DoStuff();
for(const auto& class : user_classes){
class->update();
}
DoStuff();
}
Shutdown();
}
private:
void DoStuff();
void Shutdown();
// ...
};
it can be done by initializing static variables
Yes, here's an example.
This is similar to #fabian's answer, but:
You don't need to manually register the classes.
The classes are not constructed automatically, you do it when you need them.
run on gcc.godbolt.org
#include <cstddef>
#include <iostream>
#include <memory>
#include <vector>
class BaseLow
{
template <typename T> friend class Base;
using factory_func_t = std::unique_ptr<BaseLow>(*)();
static std::vector<factory_func_t> &GetFactoryFuncsMutable()
{
static std::vector<factory_func_t> ret;
return ret;
}
public:
virtual ~BaseLow() {}
virtual void foo() = 0;
static std::vector<factory_func_t> &GetFactoryFuncs()
{
return GetFactoryFuncsMutable();
}
};
template <typename T>
class Base : public BaseLow
{
static std::nullptr_t RegisterSelf()
{
GetFactoryFuncsMutable().push_back([]() -> std::unique_ptr<BaseLow>
{
return std::make_unique<T>();
});
return nullptr;
}
inline static const std::nullptr_t dummy = RegisterSelf();
// Force `dummy` to be instantiated.
static constexpr std::integral_constant<decltype(&dummy), &dummy> dummy_helper{};
};
struct A : Base<A>
{
void foo() override
{
std::cout << "I'm A!\n";
}
};
struct B : Base<B>
{
void foo() override
{
std::cout << "I'm B!\n";
}
};
int main()
{
std::vector<std::unique_ptr<BaseLow>> objects;
for (const auto &func : BaseLow::GetFactoryFuncs())
objects.push_back(func());
for (auto &obj : objects)
obj->foo();
}
But how can my library create instance of user classes?
You can't but you can provide the user with a convenient way of adding a instance. You could e.g. provide a template class that registers an instance of a class in the constructor which allows the user to add an instance by simply defining an instance of this class.
Example
(Static) Library
Base.h
int main(int, char**);
template<typename T>
class BaseRegistrar
{
public:
BaseRegistrar();
};
class Base
{
public:
Base();
virtual ~Base();
virtual void start() = 0;
virtual void update() = 0;
private:
static std::vector<std::unique_ptr<Base>>& GetBaseInstances();
friend int main(int, char**);
template<typename T>
friend class BaseRegistrar;
};
template<typename T>
BaseRegistrar<T>::BaseRegistrar()
{
Base::GetBaseInstances().emplace_back(new T);
}
Base.cpp
#include "Base.h"
Base::Base(){}
Base::~Base(){}
std::vector<std::unique_ptr<Base>>& Base::GetBaseInstances()
{
static std::vector<std::unique_ptr<Base>> instances;
return instances;
}
main.cpp
#include "Base.h"
int main(int argc,char** argv)
{
for(auto& clazz : Base::GetBaseInstances()){
clazz->start();
}
for(auto& clazz : Base::GetBaseInstances()){
clazz->update();
}
}
Executable
MyClass.cpp
#include "Base.h"
#include <iostream>
class MyClass : public Base
{
public:
MyClass ()
{}
~MyClass ()
{}
virtual void start() override
{
std::cout << "MyClass::start()\n";
}
virtual void update() override
{
std::cout << "MyClass::update()\n";
}
};
// adds an instance of the class to the list
BaseRegistrar<MyClass> registrar;
Output
MyClass::start()
MyClass::update()

Creating List of abstract base class to fill with inherited objects

I want to create a List which is able to hold every Object I throw at it as long as they share the same ABSTRACT base class.
Here is an sample code of how I want to achieve this.
#include <iostream>
#include <memory>
#include <list>
class Observer
{
public:
virtual void update() = 0;
};
class RequestStateObserver
{
public:
void registerObserver(std::shared_ptr<Observer> o){
observerList.push_back(o);
}
private:
std::list<std::shared_ptr<Observer>> observerList;
};
class RestRequestCreator :Observer
{
void update() override;
};
void RestRequestCreator::update()
{
std::cout<<"RestRequestCreator::update()";
}
class dbHandler :Observer
{
void update() override;
};
void dbHandler::update() {
std::cout<<"dbHandler::update()";
}
int main()
{
RestRequestCreator rrc;
RequestStateObserver rso;
dbHandler dbhandler;
std::shared_ptr<RequestStateObserver> stateObserver;
std::shared_ptr<RestRequestCreator> rr_ptr = std::make_shared<RestRequestCreator>(rrc);
rso.registerObserver(rr_ptr);
rso.registerObserver(std::make_shared<Observer> (dbhandler));
}
o->registerObserver(std::make_shared<Observer> dbhandler)will tell me I can't create Observer since it's an abstract class which totally makes sense but
o->registerObserver(rr_ptr) will tell me it can't convert std::shared_ptr<Observer> to std::shared_ptr<RestRequestCreator>
I am at the moment not sure how to fix this problem or what exactly I should try next.
Would Templates help me? If I am correct they would just allow me to put as many objects of ONE child class into my List, if that's wrong please tell me and I will re-read about templates again.
The conversion fails because Observer is a private base of RestRequestCreator, and is inaccessible.
You'll need to use public inheritance for the compiler to implicitly convert from the derived class to the base:
class RestRequestCreator :public Observer
That fixes the immediate problem, but leaves the problems with make_shared<Observable> on the next line.
Also: should an observee co-own an observer? In general that would not be the case. Therefore, instead use regular pointers.
#include <list>
#include <iostream>
using std::cout;
class Observer
{
public:
virtual void update() = 0;
};
class ConcreteObserver : public Observer
{
public:
void update() override {
cout << "ConcreteObserver noticed update\n";}
};
class OtherKindConcreteObserver : public Observer
{
public:
void update() override {
cout << "OtherKindObserver noticed update\n";
}
};
class Subject
{
public:
void registerObserver( Observer* o) {
observerList.push_back( o);
}
void signalObservers() {
for ( auto observer : observerList)
observer->update();
}
private:
std::list<Observer*> observerList;
};
int main() {
ConcreteObserver observer1;
OtherKindConcreteObserver observer2;
Subject subject;
subject.registerObserver( &observer1);
subject.registerObserver( &observer2);
subject.signalObservers();
return 0;
}

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.

Subclass of class that inherits from enable_shared_from_this returning shared_ptr of self

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.

Right design pattern to deal with polymorphic collections of objects

Suppose I have the following classes:
class BaseObject {
public:
virtual int getSomeCommonProperty();
};
class Object1: public BaseObject {
public:
virtual int getSomeCommonProperty(); // optional
int getSomeSpecificProperty();
};
class BaseCollection {
public:
virtual void someCommonTask();
};
class Collection1: public BaseCollection {
public:
virtual void someCommonTask(); // optional
void someSpecificTask();
};
Each collection, derived from BaseCollection, deals with a specific object type (and only one type). But BaseCollection should be able to perform some tasks that are common to all objects, using only common object properties in BaseObject.
Currently, I have potentially three solutions in mind:
1) Store the objects list in BaseCollection, such as:
class BaseCollection {
vector<BaseObject*> objects;
};
The problem with this solution is that when I need to perform object-specific task in Collection1, I need a dynamic_cast<>, because I don't want to use virtual inherance for specific properties, applying to only one type of object. Considering that dynamic_cast<> could potentially get called millions of time per second, this seems an issue for a performance critical application.
2) Store the objects list in Collection1, such as:
class Collection1: public BaseCollection {
vector<Object1*> objects;
}
But then I need some way to access this object list in BaseCollection, to be able to perform some common tasks on them, ideally through an iterator. I would need to create a function that return a vector for the BaseCollection, but again, this does not seem very efficient, because the only way to do that is to create a new vector (potentially containing thousands of objects)...
3) Store the objects list in BaseCollection AND Collection1:
class BaseCollection {
public:
void someCommonTask(); // Use baseObjects
virtual void addObject() = 0;
protected:
vector<BaseObject*> baseObjects;
};
class Collection1: public BaseCollection {
vector<Object1*> objects;
public:
virtual void addObject() {
Object1* obj = new Object1;
objects.push_back(obj);
baseObjects.push_back(obj);
}
void someSpecificTask(); // Use objects, no need of dynamic_cast<>
}
Where the two lists actually contain the same objects. Is that as ugly as it sounds like?
I am looking for the right/correct/best design pattern for this type of problem and none of the 3 solutions exposed above really satisfies me...
Maybe it is possible to solve that problem with templates, but then I don't see a way to store a list of polymorphic collections like this:
vector<BaseCollection*> collections;
You can store all your objects of base and derived classes in one collection through the base class (smart) pointer. Using visitor design pattern and double dispatch mechanism you can call a function only on objects of a specific type without having to expose that function in the base class interface. For example:
#include <boost/intrusive_ptr.hpp>
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
#include <stdio.h>
struct Visitor { // Visitor design patter
virtual void visit(struct BaseObject&) {}
virtual void visit(struct Object1&) {}
};
struct BaseObject {
unsigned ref_count_; // intrusive_ptr support
BaseObject() : ref_count_() {}
virtual ~BaseObject() {}
virtual void accept(Visitor& v) { v.visit(*this); } // Visitor's double dispatch
virtual void getSomeCommonProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
};
void intrusive_ptr_add_ref(BaseObject* p) { // intrusive_ptr support
++p->ref_count_;
}
void intrusive_ptr_release(BaseObject* p) { // intrusive_ptr support
if(!--p->ref_count_)
delete p;
}
struct Object1 : BaseObject {
virtual void accept(Visitor& v) { v.visit(*this); } // Visitor's double dispatch
virtual void getSomeCommonProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
void getSomeSpecificProperty() { printf("%s\n", __PRETTY_FUNCTION__); }
};
template<class T, class Functor>
struct FunctorVisitor : Visitor {
Functor f_;
FunctorVisitor(Functor f) : f_(f) {}
void visit(T& t) { f_(t); } // apply to T objects only
template<class P> void operator()(P const& p) { p->accept(*this); }
};
template<class T, class Functor>
FunctorVisitor<T, Functor> apply_to(Functor f)
{
return FunctorVisitor<T, Functor>(f);
}
int main()
{
typedef boost::intrusive_ptr<BaseObject> BaseObjectPtr;
typedef std::vector<BaseObjectPtr> Objects;
Objects objects;
objects.push_back(BaseObjectPtr(new BaseObject));
objects.push_back(BaseObjectPtr(new Object1));
for_each(
objects.begin()
, objects.end()
, boost::bind(&BaseObject::getSomeCommonProperty, _1)
);
for_each(
objects.begin()
, objects.end()
, apply_to<BaseObject>(boost::bind(&BaseObject::getSomeCommonProperty, _1))
);
for_each(
objects.begin()
, objects.end()
, apply_to<Object1>(boost::bind(&Object1::getSomeSpecificProperty, _1))
);
}
Output:
$ ./test
virtual void BaseObject::getSomeCommonProperty()
virtual void Object1::getSomeCommonProperty()
virtual void BaseObject::getSomeCommonProperty()
void Object1::getSomeSpecificProperty()
I think you should go for option 1 but use a static cast instead. After all the derived collection knows the type of the member variable for sure.
This answer explains it very well.
Id use nested adapter as in below example. You have to specialize it for every class you want to do a fancy update
!The example has memory leak - allocated A, B, Q objects are not deleted!
#include <iostream>
#include <vector>
#include <algorithm>
class Q
{
public:
virtual void Foo()
{
std::cout << "Q::Foo()" << std::endl;
}
};
class A
{
public:
virtual void Foo()
{
std::cout << "A::Foo()" << std::endl;
}
};
class B : public A
{
public:
virtual void Foo()
{
std::cout << "B::Foo()" << std::endl;
}
virtual void BFoo()
{
std::cout << "B::BFoo()" << std::endl;
}
};
template <typename ElementType>
class C
{
public:
template <typename T>
void add(T* ptr){m_Collection.push_back(std::unique_ptr<Adapter>(new ConcreteAdapter<T>(ptr)));}
void updateAll()
{
std::for_each(m_Collection.begin(), m_Collection.end(), [&](std::unique_ptr<Adapter> &adapter)->void{adapter->update();});
}
private:
class Adapter
{
public:
virtual ElementType* get() = 0;
virtual void update(){get()->Foo();}
};
template <typename T>
class ConcreteAdapter : public Adapter
{
public:
ConcreteAdapter(T* ptr) : m_Ptr(ptr){}
virtual T* get(){return m_Ptr;}
protected:
T* m_Ptr;
};
template <>
class ConcreteAdapter<B> : public Adapter
{
public:
ConcreteAdapter(B* ptr) : m_Ptr(ptr){}
virtual B* get(){return m_Ptr;}
virtual void update()
{
get()->Foo();
get()->BFoo();
}
private:
B* m_Ptr;
};
std::vector<std::unique_ptr<Adapter>> m_Collection;
};
int main()
{
C<A> c;
c.add(new A());
c.add(new B());
//c.add(new Q()); //error - correct
c.updateAll();
return 0;
}
Maybe this will do the trick here ?
class CollectionManipulator {
public:
void someCommonTask(BaseCollection& coll) {
for(unsigned int i = 0; i < coll.size(); i++)
someCommonTask(coll.getObj(i));
}
private:
void someCommonTask(BaseObject*); // Use baseObjects
};
class BaseCollection {
friend class CollectionManipulator;
private:
virtual BaseObject* getObj(unsigned int) = 0;
virtual unsigned int size() const = 0;
};
class Collection1 : public BaseCollection {
vector<Object1*> objects;
public:
virtual void addObject() {
Object1* obj = new Object1;
objects.push_back(obj);
baseObjects.push_back(obj);
}
void someSpecificTask(); // Use objects, no need of dynamic_cast<>
private:
BaseObject* getObj(unsigned int value) {
return object[value];
}
unsigned int size() const {
return objects.size();
}
}
If you want abstract your container in Collection1 (like using list instead using vector), to use it in Manipulator, create an abstract iterator...
I think the solution should be a mix of factory method pattern and template method pattern. Take a look at those to refine your design.
Edit: Here is a sample code. GenericProduct is the BaseObject, it provides two methods, one that is general (though it could be overridden), and a specific method which does nothing, it is not a pure virtual so this class can be instantiated. SpecificProduct is a subclass, which implements the specific method in some way.
Now, Factory class is an abstract class that defines an interface for creating specific products by specific factories, it defines a pure virtual method createProduct which creates the product. Two concrete factories are created GenericFactory and SpecificFactory which create specific products.
Finally, the Consumer abstract class (which corresponds to BaseCollection in your code), it defines a pure virtual method for creating a factory createFactory in order to force subclasses to create their own concrete factories (and hence, the correct products). The class also define a method fillArray (prototype pattern) to fill the array with products created by the factory.
#include <iostream>
#include <vector>
using namespace std;
class GenericProduct{
public:
virtual void getSomeCommonProperty()
{
cout<<"Common Property\n";
}
virtual void getSomeSpecificProperty()
{
cout<<"Generic Has Nothing Specific\n";
}
};
class SpecificProduct : public GenericProduct{
public:
virtual void getSomeSpecificProperty()
{
cout<<"Specific Product Has a Specific Property\n";
}
};
class Factory
{
public:
virtual GenericProduct* createProduct() = 0;
};
class GenericFactory : public Factory
{
public:
virtual GenericProduct* createProduct()
{
return new GenericProduct();
}
};
class SpecificFactory : public Factory
{
public:
virtual GenericProduct* createProduct()
{
return new SpecificProduct();
}
};
class Consumer
{
protected:
vector<GenericProduct*> gp;
Factory* factory;
protected:
virtual void createFactory() = 0;
public:
void fillArray()
{
createFactory();
for(int i=0; i<10; i++)
{
gp.push_back(factory->createProduct());
}
}
virtual void someCommonTask()
{
cout<<"Performaing a Common Task ...\n";
for(int i=0; i<10; i++)
{
gp[i]->getSomeCommonProperty();
}
}
virtual void someSpecificTask()
{
cout<<"Performaing a Specific Task ...\n";
for(int i=0; i<10; i++)
{
gp[i]->getSomeSpecificProperty();
}
}
};
class GenericConsumer : public Consumer
{
virtual void createFactory()
{
factory = new GenericFactory();
}
};
class SpecificConsumer : public Consumer
{
virtual void createFactory()
{
factory = new SpecificFactory();
}
};
int main()
{
Consumer* c = new GenericConsumer();
c->fillArray();
c->someCommonTask();
return 0;
}