Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer on class contructor

Tags:

c++

std

I'm working on a personal project and I need to have a dynamic factory. Currently I have the following "system" :

class Action { ...} // Which is abstract
class A : public Action { ... }
class B : public Action { ... }
class C : public Action { ... }

...

std::map<std::string, Action *> _actions;
_action.insert( { "A", new A() } );
_action.insert( { "B", new B() } );
_action.insert( { "C", new C() } );

Action * act = _actions.find("B")->second; // Get action's pointer

But I'm not satisfied by this solution because, even if I never use these actions, they are instantiated at boot and stay in memory during all the application's life-cycle and if I want to have a "clean" object, I need to cast dynamically my object to determine its type to call the constructor by copy... I'm not really fan of this solution because I must "hard code" all cases...

I don't know if the solution that I imagine is really feasible but here is my idea :

I conserve the previous class hierarchy, which is :

class Action { ...} // Which is abstract
class A : public Action { ... }
class B : public Action { ... }
class C : public Action { ... }

But I want to use the map differently :

std::map<std::string, POINTER_ON_CLASS_CONSTRUCTOR> _actions;
_actions.insert( { "A", &A::A } );
_actions.insert( { "B", &B::B } );
_actions.insert( { "C", &C::C } );

Action * act = new (_actions.find("B")->second);

To resume my idea :

I want to map a key with a pointer on each constructor I want to map and then, instantiate dynamically an action-based object according to the key.

Thanks per advance for your help and if you have a suggestion to solve this issue, do not hesitate to submite it :)


Context :

I'm creating a CLI for my software and if I want to code this solution is to map the first word of an action with a associated action.

Example : If I enter "add file.txt", "add" will be the key of my map to retrieve a "clean" instance on the class "AddAction" (which is a child of Action - which is abstract and common to all action-based class).

Edit : before posting this question, I've searched on the web and on this forum but I haven't found what I was looking for.. :/

like image 951
arnaudm Avatar asked Aug 12 '26 00:08

arnaudm


1 Answers

You could map the names to factory functions, then call those functions each time you want to create a new instance. Wrapping it in a unique_ptr will give you the destruction you want after use. live link

std::unordered_map<std::string, std::function<std::unique_ptr<Action>()>> ACTIONS = {
  {"A", [] { return std::make_unique<A>(); }},
  {"B", [] { return std::make_unique<B>(); }},
  {"C", [] { return std::make_unique<C>(); }}
};

int main() {
  auto action = ACTIONS["A"]();
}
like image 112
Ryan Haining Avatar answered Aug 14 '26 15:08

Ryan Haining



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!