Reputation: 1626
I'm wondering about an idea in my head. I want to ask if you know of any library or article related to this. Or you can just tell me this is a dumb idea and why.
I have a class, and I want to dynamically add methods/properties to it at runtime. I'm well aware of the techniques of using composite/command design pattern and using embedded scripting language to accomplish what I'm talking about. I'm just exploring the idea. Not necessary saying that it is a good idea.
class Dynamic
{
public:
typedef std::map<std::string, boost::function<void (Dynamic&)> > FuncMap;
void addMethod(const std::string& name, boost::function<void (Dynamic&)> func) {
funcMap_[name] = func;
}
void operator[](const std::string& name) {
FuncMap::iterator funcItr = funcMap_.find(name);
if (funcItr != funcMap_.end()) {
funcItr->second(*this);
}
}
private:
FuncMap funcMap_;
};
void f(Dynamic& self) {
doStuffWithDynamic(self);
}
int main()
{
Dynamic dyn;
dyn.addMethod("f", boost::bind(&f, _1));
dyn["f"]; // invoke f
}
The idea is that I can rebind the name "f" to any function at runtime. I'm aware of the performance problem in string lookup and boost::function vs. raw function pointer. With some hard work and non-portable hack I think I can make the performance problem less painful.
With the same kind of technique, I can do "runtime inheritance" by having a "v-table" for name lookup and dispatch function calls base on dynamic runtime properties.
If just want to tell me to use smalltalk or Objective-C, I can respect that but I love my C++ and I'm sticking with it.
Upvotes: 0
Views: 558
Reputation: 116674
If you implemented this, even as a pure library, and then used it extensively, you would in a way be using a new language - one with a hideous syntax, and a curious combination of runtime method resolution and unreliable bounds checking.
As a fan of C/C++ style syntax and apparently a fan of dynamic method dispatch, you may be interested in C# 4.0, which is now in Beta, and has the dynamic
keyword to allow exactly this kind of thing to be seamlessly mixed into normal statically typed code.
Upvotes: 3
Reputation: 29450
If I understand what you are trying to accomplish correctly, it seems as though dynamic linking (i.e. Dynamically loaded libraries in windows or linux) will do most of what you are trying to accomplish.
That is, you can, at runtime, select the name of the function you want to execute (eg. the name of the DLL), which then gets loaded and executed. Much in the way that COM works. Or you can even use the name of the function exported from that library to select the correct function (C++ name mangling issues aside).
Upvotes: 1
Reputation: 20041
I've considered doing this before as well. Basically, however, you'd be on your way to writing a simple VM or interpreter (look at, say, Lua or Topaz's source to see what I mean -- Topaz is a dead project that pre-dates Parrot).
But if you're going that route it makes sense to just use an existing VM or interpreter.
Upvotes: 0
Reputation: 35485
What you are doing is actually a variation of the Visitor pattern.
EDIT: By the way, another approach would be by using Lua, since the language allows you to add functions at runtime. So does Objective-C++.
EDIT 2: You could actually inherit from FuncMap as well:
class Dynamic;
typedef std::map<std::string, boost::function<void (Dynamic&)> > FuncMap;
class Dynamic : public FuncMap
{
public:
};
void f(Dynamic& self) {
//doStuffWithDynamic(self);
}
int main()
{
Dynamic dyn;
dyn["f"] = boost::bind(&f, _1);
dyn["f"](dyn); // invoke f, however, 'dyn'param is awkward...
return 0;
}
Upvotes: 1
Reputation: 4186
I keep thinking of the Visitor pattern. That allows you to do a vtable lookup on the visiting object (as well as the visited object, thought that doesn't seem relevant to your question).
And at runtime, you could have some variable which refers to the visitor, and call
Dynamic dynamic;
DynamicVisitor * dv = ...;
dynamic->Accept(dv);
dv = ...; // something else
dynamic->Accept(dv);
The point is, the visitor object has a vtable, which you said you wanted, and you can change its value dynamically, which you said you wanted. Accept is basically the "function to call things I didn't know about at compile time."
Upvotes: 0
Reputation: 12044
What you want is to change C++ into something very different. One of the (many) goals of C++ was efficient implementation. Doing string lookup for function calls (no matter how well you implement it), just isn't going to be very efficient compared to the normal call mechanisms.
Basically, I think you're trying to shoehorn in functionality of a different language. You CAN make it work, to some degree, but you're creating C++ code that no one else is going to be able (or willing) to try to understand.
If you really want to write in a language that can change it's objects on the fly, then go find such a language (there are many choices, I'm sure). Trying to shoehorn that functionality into C++ is just going to cause you problems down the road.
Please note that I'm no stranger to bringing in non-C++ concepts into C++. I once spent a considerable amount of time removing another engineer's attempt at bringing a based-object system into a C++ project (he liked the idea of containers of 'Object *', so he made every class in the system descend from his very own 'Object' class).
Bringing in foreign language concepts almost always ends badly in two ways: The concept runs up against other C++ concepts, and can't work as well as it did in the source language, AND the concept tends to break something else in C++. You end up losing a lot of time trying to implement something that just isn't going to work out.
The only way I could see something like this working at all well, is if you implemented a new language on top of C++, with a cfront-style pre-compiler. That way, you could put some decent syntax onto the thing, and eliminate some of your problems.
Upvotes: 8
Reputation: 57036
I don't think it would be a good idea to change C++ enough to make this work. I'd suggest working in another language, such as Lisp or Perl or another language that's basically dynamic, or imbedding a dynamic language and using it.
Upvotes: 2
Reputation: 67749
I don't think there's a library for this exact thing.
Of course, you have to have these functions pre-written somehow, so it seems there would be an easier way to do what you want. For example you could have just one method to execute arbitrary code from your favorite scripting language. That seems like an easier way to do what you want.
Upvotes: 0