Keeping track of member arguments of derived class - c++

Let's say I have a library with a virtual class called INode. The user of the library is suposed to use INode for creation of multiple concrete nodes (e.g. single ConcreteNode) with any kind of functionality specialized by the user.
Right now, if inside of any ConcreteNode I want to declare a "special" scalar argument, I call arguments.scalar.add(0) method, witch creates me a new entry inside an intern vector of scalar values (is it practically std::vector<double>) and initiates it with an id = 0. Besides the named vector of doubles called scalar I also prepared containers with vectors (arguments.vector.) and matrices (argument.matrix.) to be called in the same way as shown.
All of this is motivated with the thought, that I want to keep track of the state (e.g. bool is_set;) for all arguments of ConcreteNode. This must happen "internally", such that the creator of ConcreteNode does not need to keep track of these arguments manually via creation of such state variables.
My current approach works, but it is limited to predefined containers (scalar, vector, matrix). Is the library used wanted to use some other data type, he must add a new entry inside INodeclass. Second issue is, that if I create ConcreteNode witch is only using a single scalar argument, containers for vectors and matrices are also created. This leads to dead code, unnecessary memory usage and the most important part is that I am making requests on all containers like bool arguments.are_set(); witch checks through all of the arguments, even if there are none of them created for vector and matrix.
I am searching for a better solution. One thought was, what if I will overload new operator inside INode class, such that every newly created argument of any type inside derived class is internally registered in the way that is it is given few state arguments and few standard functions set/get.
Then the code might be way flexible and probably look like this:
struct ConcreteNode : INode
{
ConcreteNode() { bool* arg = new bool; }
void foo() override { /* ... use arg ... */ };
}
On this point I ask myself if this boilerplate with new is really necessary. Couldn't I just create a wrapper around the new operator to make it look like normal member initialization like bool arg;. Or maybe I am missing some clever trick in cpp witch allows me keep track of created members directly.
I hope I did the point of my thoughts clear and you could help me to go further with them.
EDIT1: Also I was thinking about making some template structures witch might behave like.
struct ConcreteNode : INode
{
ConcreteNode()
{ arguments.add<bool>("arg");
arguments.set<bool>("arg") = true; }
void foo() override { /* ... bool b = arguments.get<bool>("arg"); ... */ };
}
EDIT2: Right now, for the current state of code I declare new arguments inside derived class like this:
struct ConcreteNode : INode
{
ConcreteNode(double a, std::vector<double> b)
{ arguments.add.scalar(0);
arguments.add.vector(1);
arguments.set.scalar(0) = a;
arguments.set.vector(1) = b;
}
void foo() override
{
double c = arguments.get.scalar(0);
std::vector<double> d = arguments.get.vector(1);
// ...
};
}

Related

Downcast from a container of Base* to Derived* without explicit conversion

I am writing a scientific code which needs to create 3-dimensional cells, defined by a set of faces, which are defined by a set of vertices.
These 3 classes (Cell, Face, Vertex) are derived respectively from some generic geometry classes (Polyhedron, Polygon, Point) which implement some geometric routines like Polygon::CalculateArea().
The Face class adds to the Polygon class with additional data and functions required for the science, like Face::Interpolate(). I don't want to make these member functions virtual in the base class (Polygon).
Now, the problem. I initialize a Cell with a vector of pointers to Face, which is handled by the base class Polyhedron constructor, which upcasts the Face* to Polygon*:
Polyhedron::Polyhedron( std::initializer_list<Polygon*> polygons );
Later, I want to access the Face* stored in a Cell so that I can call Face::Interpolate(), but it has been stored as a Polygon* and thus has no member function Polygon::Interpolate(). I can downcast it manually back to a Face* which works, but is not very clean. The user of the code has to do something like:
Face * temp_face = (Face*)cell->GetFaces()[0]; // Could use static_cast
temp_face->Interpolate();
which is not obvious.
I want the interface to be transparent, so that this just works:
cell->GetFaces()[0]->Interpolate();
I can think of two or three ways to achieve this. I'm looking for a better solution or feedback of which of these is recommended:
In Cell::GetFaces() which currently just inherits from Polyhedron::GetPolygons() I could create a wrapper that copies the std::vector<Polygon*> to a new vector std::vector<Face*>. This seems sloppy to me, not easy to maintain, inefficient and prone to errors.
Instead of storing std::vector<Polygon*> I could store std::vector<std::shared_ptr<Polygon>>. From what I understand, these smart pointers retain type-awareness so that they can call the right destructor, but they might just store a reference to the destructor depending on implementation. I don't want to use shared_ptr for performance purposes -- I know they're good and friendly, but I'm creating millions of these Polygons and its easy to destroy them in the right place. I can't use unique_ptr easily because of the copy-constructor used in std::initializer_list constructors.
Template the whole Polyhedron class, replacing every instance of Polygon* with F* and checking that F is a base of Polygon:
template<typename F = Polygon>
typename std::enable_if<std::is_base_of<Polygon, F>::value, void>::type
class Polyhedron
and then inheriting from a parent with a given typename:
class Cell : public Polyhedron<Face>
This seems like the best method to me, since it has the least boilerplate and nothing exposed to the user; but it still feels messy, especially in the "real" case where there might be multiple types that would all have to be specified:
class Cell: public Polyhedron<Face,Vertex,type3,type4,type5,...>
Is there a a better way? Perhaps a means of retaining type in the original vector (or some other container)?
If not, which of the above methods is the best practice and why?
Edit:
Here's an abstracted view of the problem. The problem occurs when trying to run sumOfSomethingSpecific(). In my actual problem, that function is inside a derived class Derived_B, which is designed to work with Derived_A, but for the sake of the problem, it makes no difference.
class Base_A
{
public:
Base_A();
~Base_A();
// I don't want virtual doSomethingSpecific() here.
};
class Derived_A
{
public:
using Base_A::Base_A;
double doSomethingSpecific();
};
// I could template this whole class
// template <typename T>
// where T replaces Base_A
class B
{
public:
// This can be initialized with:
// std::vector<Derived_A*>
// which is what I want to do, but we lose info about doSomethingSpecific()
// even if I write a separate constructor its still stored as
// std::vector<Base_A*>
B(std::vector<Base_A*> v) : v(v) {};
~B();
double sumOfSomethingSpecific()
{
double sum = 0;
for(auto&& A : v) {
// Can't do this, A is a pointer of type Base_A*, but this is the abstraction that I want to achieve
sum += A->doSomethingSpecific();
// Could do this, but its ugly and error-prone
Derived_A* tempA = (Derived_A*)A;
sum += tempA->doSomethingSpecific();
}
return sum;
}
protected:
std::vector<Base_A*> v;
};
First most of issues you're facing here are not about programming, are about design.
... class with additional data and functions required for the science, like Face::Interpolate(). I don't want to make these member functions virtual in the base class (Polygon). ...
Well, don't do that, but then you have to realize that you're adding complexity to the code you need to implement such design desicion.
However, if every polygon can be "interpolated" then you should have a virtual function (or better yet a pure virtual function) in your Polygon class.
Said that, with the code as it is, in order to add transparency to the API you declare you get_* functions as:
void GetFaces(std::vector<Face *> &faces);
that way is clear for the user that he/she has to provide a reference to a vector of faces to get the result. Lets see how this change your code:
// Face * temp_face = (Face*)cell->GetFaces()[0]; // Could use static_cast
std::vector<Face *> temp_faces;
cell->GetFaces(temp_faces);
//temp_face->Interpolate();
temp_faces[0]->Interpolate();
This way the down-cast is performed implicitly.
About your question: Is there a a better way? Yes, redesign your classes.
About your example:
I will ask you to think a moment about this:
struct Base {};
struct Derived_A: Base { double doSomethingSpecific(); };
struct Derived_B: Base { double doSomethingSpecific(); };
int main()
{
std::vector<Base*> base_v = {/*suppose initialization here*/};
base_v[0]->doSomethingSpecific(); // Which function must be called here?
// Derived_A::doSomethingSpecific or
// Derived_B::doSomethingSpecific.
}
At some point you will have to tell wich type you want call the function on.
The level of abstraction you want, does not exists in C++. The compiler needs to know the type of an object in order to perform (compile) a call to one of its member functions.
Another approach you can try (I still recommend to redesign):
If you have the need of manipulating several distinct types in a uniform manner. Perhaps you want to take a look at Boot.Variant library.
I struggled with a similar problem in one of my projects. The solution I used was to give ownership of the actual objects to the most-derived class, give the base class a copy of the objects, and use a virtual function to keep the copy up-to-date as objects are added/removed:
class Polyhedron {
protected:
bool _polygons_valid = false;
std::vector<Polygon*> _polygons;
virtual void RebuildPolygons() = 0;
public:
std::vector<Polygon*>& GetPolygons()
{
if (!_polygons_valid) {
RebuildPolygons();
_polygons_valid = true;
}
return _polygons;
}
/*Call 'GetPolygons()' whenever you need access to the list of polygons in base class*/
};
class Cell: public Polyhedron {
private:
std::vector<Face*> _faces; //Remember to set _polygons_valid = false when modifying the _faces vector.
public:
Cell(std::initializer_list<Face*> faces):
_faces(faces) {}
//Reimplement RebuildPolygons()
void RebuildPolygons() override
{
_polygons.clear();
for (Face* face : _faces)
_polygons.push_back(face);
}
};
This design has the benefits of clear ownership (most-derived class is owner), and that copying and upcasting the vector of object pointers is done only when needed. The downside is that you have two copies of essentially the same thing; a vector of pointers to objects. The design is very flexible too, since any class derived from Polyhedron only has to implement the RebuildPolygons() function, using a vector of any type derived from Polygon.

"Addition" of two classes

I've been doing some dynamical system simulations in a rather crude functional way and am currently trying to figure out what can cpp objects bring to my code. More specifically, I was thinking about the following construction:
I would like to specify the dynamical system by an abstract class, say "DynSys", with a purely virtual method specifying the dynamics (say "energy" and others). Once I derive two concrete classes from DynSys, I would like to do a "superposition" of their instances in the sense of creation of a new DynSys object that returns an addition of the two respective dynamical member functions. Is this possible? E.G.:
DynamicHole Blackhole; // DynSys derived
DynamicDisc Disc; // DynSys as well
vector state; // eg a dynamical array of numbers
Blackhole.energy(state); // returns A(state)
Disc.energy(state); // returns B(state)
??class?? HoleDisc = DynamicAddition(&Blackhole,&Disc); // is a DynSys
HoleDisc.energy(state); // returns A(state)+B(state)
The pointer to a DynSys object is passed to the simulation itself, so it is important for the result to be a DynSys object.
I saw some constructions using the "+" operator or befriending to add the parameters of the class. However, the problem here seems to be the fact that the addition process involving method addition would need to define a completely new concrete class.
I see a rather inelegant workaround by defining the "core" functions A(state,parameters), B(state,parameters) separately and then defining the superposition class by hand. I have quite a lot of superpositions to make, so I wondered whether there was a better way to do this.
If I understand correctly, when you "add" to DynSys together you want to create some aggregation. Here is a pseudocode that could be adapted to your needs:
class DynSysGroup : public DynSys
{
DynSys& m_a;
DynSys& m_b;
public:
DynSysGroup(DynSys& a, DynSys& b) : m_a(a), m_b(b) { }
// I'm guessing the signature of energy()...
void energy(vector& v)
{
// Get A(state) with m_a
// Get B(state) with m_b
// Do A(state) + B(state)
}
}
And your line above
??class?? HoleDisc = DynamicAddition(&Blackhole,&Disc); // is a DynSys
would become
DynSysGroup HoleDisc(Blackhole, Disc);
Of course, with reference like m_a and m_b you need to make sure you don't get dangling reference. Maybe you'll need to use smart pointers like std::shared_ptr.
Side note: you may want to look into std::valarray and change the way energy() works: instead of taking a vector as parameter, you could simply return it (it if fits your design, of course).
std::valarray DynSys::energy() const { return ...; }

Dynamic mapping of enum value (int) to type

It appeared that this problem is quite common in our job.
We we are sending an int or enum value through the network, then we receive it we would like to create/call a particular object/function.
The most simply solution would be to use the switch statement, like below:
switch (value) {
case FANCY_TYPE_VALUE: return new FancyType();
}
It works fine, but we would have plenty of these switch blocks, and when we create new value and type, we would need to change all of them. It does seem right.
Other possibility would be to use the templates. But we cannot, since the value of enum is defined in runtime.
Is there any right design pattern for that, or any right approach?
It seems like a very general and common problem in every day coding...
Try a map:
struct Base { };
struct Der1 : Base { static Base * create() { return new Der1; } };
struct Der2 : Base { static Base * create() { return new Der2; } };
struct Der3 : Base { static Base * create() { return new Der3; } };
std::map<int, Base * (*)()> creators;
creators[12] = &Der1::create;
creators[29] = &Der2::create;
creators[85] = &Der3::create;
Base * p = creators[get_id_from_network()]();
(This is of course really crude; at the very least you'd have error checking, and a per-class self-registration scheme so you can't forget to register a class.)
You can actually do this with some template trickery:
#include <map>
template <typename Enum, typename Base>
class EnumFactory {
public:
static Base* create(Enum e) {
typename std::map<Enum,EnumFactory<Enum,Base>*>::const_iterator const it = lookup().find(e);
if (it == lookup().end())
return 0;
return it->second->create();
}
protected:
static std::map<Enum,EnumFactory<Enum,Base>*>& lookup() {
static std::map<Enum,EnumFactory<Enum,Base>*> l;
return l;
}
private:
virtual Base* create() = 0;
};
template <typename Enum, typename Base, typename Der>
class EnumFactoryImpl : public EnumFactory<Enum,Base> {
public:
EnumFactoryImpl(Enum key)
: position(this->lookup().insert(std::make_pair<Enum,EnumFactory<Enum,Base>*>(key,this)).first) {
}
~EnumFactoryImpl() {
this->lookup().erase(position);
}
private:
virtual Base* create() {
return new Der();
}
typename std::map<Enum,EnumFactory<Enum,Base>*>::iterator position;
};
This allows you to create a new derived object from a given enum, by saying
// will create a new `FancyType` object if `value` evaluates to `FANCY_TYPE_VALUE` at runtime
EnumFactory<MyEnum,MyBase>::create(value)
However, you have to have some EnumFactoryImpl objects, which could be static in some function or namespace.
namespace {
EnumFactoryImpl<MyEnum,MyBase,Derived1> const fi1(ENUM_VALUE_1);
EnumFactoryImpl<MyEnum,MyBase,Derived2> const fi2(ENUM_VALUE_2);
EnumFactoryImpl<MyEnum,MyBase,Derived3> const fi3(ENUM_VALUE_3);
EnumFactoryImpl<MyEnum,MyBase,FancyType> const fi1(FANCY_TYPE_VALUE); // your example
}
These lines are the single point where your source code maps enum values to derived types. So you have everything at the same location, and no redundancy (this eliminates the problem of forgetting to change it in some places, when adding new derived types).
One option is to maintain a dictionary of creators(which has the same interface) that can create a concrete type. Now the creation code will search in the dictionary for an int value (resulting from the enum sent from the client) and call the create method, which returns the concrete object via a base-class pointer.
The dictionary can be initialized at one place with the concrete creators corresponding to each possible enum values.
The problem here is that you have to extend this dictionary initialization code when you add a new type of object. A way to avoid is as following.
Let the creator look for a singleton factory instance and register itself in the constructor with the type enums(integers) with which it can create a concret object.
Create a DLL for one/set of creators and have a global instance of the creators.
The name of the DLL can be entered in a config file which is read by the factory in the initialization. The factory loads all the DLLs in this file and this results in the creation of the static objects which registers themselves with the factory.
Now the factory has the map of all the type enums which it can create with the concrete object creators.
The same object creator look-up mechanism is implemented to create the objects.
Now, the factory doesn't need to be extended at all since step 3,4 and 5 doesn't change for new objects introduced. Step 1 can be implemented in one place.
Only thing you need to do is to add a global object for each of the new concrete type which should be there since the C++ doesn't support reflection natively.
kogut, I don't propose this as an answer, but since you ask me to expand on my comment on your original question here's a very brief summary of what the .net environment gives you...
public enum MyEnum
{
[MyAttribute(typeof(ClassNone))]
None,
[MyAttribute(typeof(ClassOne))]
One,
[MyAttribute(typeof(ClassTwo))]
Two,
[MyAttribute(typeof(ClassThree))]
Three
}
So you have your basic enum One, Two, Three etc. which works just like....er....an enum!
But you also code up a class called MyAttribute (and in fact for more information in this area, just search for Attributes). But as you can see this allows you to say, at design time, that such-and-such an enum value is associated with such-and-such a class.
This information is stored in the enum's metadata (the value of a managed environment!) and can be interrogated at runtime (using Reflection). Needless to say this is very powerful, I've used this mechanism to systematically strip out loads of maps of the kind proposed in other answers to your question.
An example of the usefulness is this...at one client I worked with, the convention was to store statuses as strings in a database on the grounds that they would be more readable to a human who needed to run a table query. But this made no sense in the applications, where statuses were pushed through as enums. Take the above approach (with a string rather than a type) and this transform happened on a single line of code as data was read and written. Plus, of course, once you've defined MyAttribute it can be tagged onto any enum you like.
My language if choice these days is c# but this would also be good in (managed) c++.

Polymorphic Enums

Polymorphic Enums?
In C++, we often use polymorphism to allow old code to handle new
code--for instance, as long as we subclass the interface expected by a
function, we can pass in the new class and expect it to work correctly
with the code that was written before the new class ever existed.
Unfortunately, with enums, you can't really do this, even though there
are occasional times you'd like to. (For instance, if you were
managing the settings for your program and you stored all of them as
enum values, then it might be nice to have an enum, settings_t, from
which all of your other enums inherited so that you could store every
new enum in the settings list. Note that since the list contains
values of different types, you can't use templates.)
If you need this kind of behavior, you're forced to store the enums as
integers and then retrieve them using typecasts to assign the
particular value to the setting of interest. And you won't even get
the benefit of dynamic_cast to help you ensure that the cast is
safe--you'll have to rely on the fact that incorrect values cannot be
stored in the list.
I'm quoting from a C++ programming tutorial.
Can anybody please explain more deeply and with some examples how Polymorphic Enums work?
And in the case I have templates?
Simply stated, an enum is simply a named constant value, for instance:
enum Settings
{
setting_number_0,
setting_number_1,
setting_number_2,
};
In the above example, setting_number_X is simply a named constant for the value X, as enumeration values start at 0 and increase monotonically.
Keeping these then, in some type of container gives a basic storage type of integers, but can still be somewhat typesafe.
std::vector<Setting> app_settings;
// this works
app_settings.push_back(setting_number_0);
// this is a compile time failure, even though the underlying storage
// type for Setting is an integral value. This keeps you from adding
// invalid settings types to your container (like 13 here)
app_settings.push_back(13);
// but you also cannot (directly) add valid setting values (like 1)
// as an integral, this is also a compile time failure.
app_settings.push_back(1);
Now, suppose you wanted to add additional specific setting types and keep them all in a container.
enum DisplaySettings
{
// ...
};
enum EngineSettings
{
// ...
};
Now, if you wanted to keep all the settings in a single container, you cannot safely. You could store all the integral values in a container of std::vector<int> or similar, but that breaks down in that you cannot determine what integral types belong to what setting enumerations. Also, since the types are different you cannot store them in a single type-safe container.
The correct way to go about this is would be to store the functionality of the setting in the container, something like this:
#include <vector>
#include <iostream>
// This is our "base class" type so we can store lots of
// different setting types in our container
class setting_action
{
public:
// we enable the setting by calling our function
void enable_setting()
{
setting_function_(this);
}
protected:
// This is a function pointer, and we're using it to get some
// compile time polymorphism
typedef void (*setting_function_type)(setting_action* setting);
// these can only be constructed by derived types, and the derived
// type will provide the polymorhpic behavior by means of the
// above function pointer and based on the derived type's handler
setting_action(setting_function_type func)
: setting_function_(func)
{
}
public:
~setting_action()
{
}
private:
setting_function_type setting_function_;
};
// This is the derived type, and where most of the magic
// happens. This is templated on our actual setting type
// that we define below
template <class Setting>
class templated_setting_action
: public setting_action
{
public:
templated_setting_action(Setting setting)
: setting_action(&templated_setting_action::enable_setting)
, setting_(setting)
{
}
// This function catches the "enable_setting" call from
// our base class, and directs it to the handler functor
// object that we've defined
static void enable_setting(setting_action* base)
{
templated_setting_action<Setting>* local_this =
static_cast<templated_setting_action<Setting>*>(base);
local_this->setting_();
}
private:
Setting setting_;
};
// this is just a shorthand way of creating the specialized types
template <class T>
setting_action* create_specialized_setting_action(T type)
{
return
new templated_setting_action<T>(type);
}
// Our actual settings:
// this one displays the user name
struct display_user_name
{
void operator()()
{
std::cout << "Chad.\n";
}
};
// this one displays a short welcome message
struct display_welcome_message
{
void operator()()
{
std::cout << "Ahh, the magic of templates. Welcome!\n";
}
};
// now, we can have one container for ALL our application settings
std::vector<setting_action*> app_settings;
int main()
{
// now we can add our settings to the container...
app_settings.push_back(create_specialized_setting_action(display_user_name()));
app_settings.push_back(create_specialized_setting_action(display_welcome_message()));
// and individually enable them
app_settings[0]->enable_setting();
app_settings[1]->enable_setting();
// also, need to delete each setting to avoid leaking the memory
// left as an exercise for the reader :)
return 0;
}

Map functions of a class

Before I was trying to map my classes and namespaces, by using static calls I succeded and now I need to map the functions of my classes because they will be used dynamically.
Firstly I was thinking to hardcode in the constructor so I can assign a std:map with the string of the name of function pointing to the function itself.
for example:
class A{
int B(){
return 1;
}
};
int main(){
A *a = new A();
vector<string, int (*)()> vec;
vector["A.B"] = a.B;
}
By that I have mapped the function B on A class, I know that I only mapped the function the instance and thats B is not static to be globally mapped.
But thats what I need, at somepoint someone will give me a string and I must call the right function of an instance of a class.
My question is if I only can do that by hardcoding at the constructor, since this is a instance scope we are talking or if there is somehow a way to do this in the declaration of the function, like here for namespaces and classes:
Somehow register my classes in a list
If I understand you correctly, you want your map to store a pointer that can be used to call a member function on an instance, the value being chosen from the map at run time. I'm going to assume that this is the right thing to do, and that there isn't a simpler way to solve the same problem. Quite often when you end up in strange C++ backwaters it's a sign that you need to look again at the problem you think you have, and see whether this is the only way to solve it.
The problem with using an ordinary function pointer is that a non-static member function is not an ordinary function. Suppose you could point to a member function with an ordinary function pointer, what would happen when you dereferenced that pointer and called the function? The member function needs an object to operate on, and the syntax doesn't provide a way to pass this object in.
You need a pointer to member, which is a slightly obscure feature with relatively tricky syntax. While an ordinary pointer abstracts an object, a pointer to member abstracts a member on a class; the pointer specifies which class member should be called, but not which object to obtain the member from (that will be specified when the pointer is used). We can use it something like this:
class B;
class A
{
B some_function()
{ /* ... */ }
};
B (A::* myval)() = A::some_function;
Here myval is a variable that indicates one of the members of class A, in this case the member some_function (though it could point to any other member of A of the same type). We can pass myval round wherever we want (e.g. storing it in an STL container, as in your example) and then when we want to call the function, we specify the instance it should be called on in order to locate the function:
A some_a;
B newly_created_b = (some_a.*myval)();
This works for a particular case, but it won't solve your general issue, because member pointers contain the class they refer to as part of the definition. That is, the following two variables are of entirely different types:
B (Foo::* first_variable)() = Foo::some_function;
B (Bar::* second_variable)() = Bar::some_function;
Even though both functions can produce a B when called without arguments, the two values operate on different classes and therefore you can't assign a value of one type to a variable of the other type. This of course rules out storing these different types in a single STL container.
If you're committed to storing these in a container, you'll have to go with a functor-based solution like Charles Salvia proposes.
If I understand you correctly, you're going to have a class like:
struct Foo
{
int bar();
};
And the user will input a string like "Foo::bar", and from that string you need to call the member function Foo::bar?
If so, it's rather awkward to code a flexible solution in C++, due to the static type system. You can use an std::map where the key is a string, and the value is a member function pointer, (or std::mem_fun_t object), but this will only work on a single class, and only on member functions with the same signature.
You could do something like:
#include <iostream>
#include <map>
#include <functional>
struct Foo
{
int bar() { std::cout << "Called Foo::bar!" << std::endl; }
};
int main()
{
std::map<std::string, std::mem_fun_t<int, Foo> > m;
m.insert(std::make_pair("Foo::bar", std::mem_fun(&Foo::bar)));
Foo f;
std::map<std::string, std::mem_fun_t<int, Foo> >::iterator it = m.find("Foo::bar");
std::mem_fun_t<int, Foo> mf = it->second;
mf(&f); // calls Foo::bar
}
just found(using google) a topic to the same question I had with an answer.
What is the simplest way to create and call dynamically a class method in C++?
I didn't try it yet but makes sense, I will ask again later if it doesn't work
ty!
Joe
I must call the right function of an instance of a class.
You need to call a specific method on an existing instance, or you need to create an instance of the appropriate type and call the method?
If it's the former, then you need a std::map or similar that lets you look up instances from their names.
If it's the latter, that's basically what serialization frameworks need to do in order to create the correct type of object when de-serializing, the object that knows how to read the next bit of data. You might take a look at how the Boost serialization library handles it:
boost.org/doc/libs/1_40_0/libs/serialization/doc/serialization.html
Are you doing this in some kind of tight loop where you need the efficiency of a good map? If so, then member function pointers (as you linked to above) is a good way to go. (At least it is after you work around the problem #Tim mentioned of keeping member function pointers to different types in the same collection ... let the language abuse begin!)
On the other hand, if this is in code that's user-driven, it might be more legible to just be totally uncool and write:
if( funcName=="A.b" )
{
A a;
a.b();
} else
// etc etc etc
For the higher-performace case, you can supplement the same approach with a parse step and some integer constants (or an enum) and use a switch. Depending on your compiler, you might actually end up with better performance than using member function pointers in a map:
switch( parse(funcName) )
{
case A_b:
{
A a;
a.b();
}
break;
}
(Of course this breaks down if you want to populate your list of possibilities from different places ... for example if each class is going to register itself during startup. But if you have that kind of object infrastructure then you should be using interfaces instead of pointers in the first place!)