Suppose I have a class for working with XML, and I want to add a method to it, but that the class does not know about it. Simple inheritance does not fit. SimpleXmlNode CreateChild(const std::string& name); use simple inheritance, then let's say the function SimpleXmlNode CreateChild(const std::string& name); will return an object that does not have a new method each and it will not be available in the script. The word mixin comes to mind, but I don’t think anything. If done on templates, you have to put everything into header files, and I really would like to avoid it.

 class SimpleXmlNode { public: explicit SimpleXmlNode(); SimpleXmlNode(const SimpleXmlNode& node); virtual ~SimpleXmlNode(); const std::string Attribute(const std::string& name) const; SimpleXmlNode operator[](const std::string& name); int AttributeInt(const std::string& name) const; // Write SimpleXmlNode CreateChild(const std::string& name); } 

I want to add the function each :

 SimpleXmlNode& each(Sqrat::Function callback) { int i = 0; for (auto& node: childs) { Sqrat::SharedPtr<bool> res = callback.Evaluate<bool>(i, node); if (!!res && *res) { break; } i++; } return *this; } 

For you to understand, Sqrat::Function callback is a callback function written in a scripting language.

I need to call each function from a script:

 node.each(function(index,elem){ /*do something*/}); 

And the class itself is registered in the scripting virtual machine:

  vm.GetRootTable().Bind("SimpleXmlNode", Class<SimpleXmlNode>(vm.GetVM(), "SimpleXmlNode"). Func("Attribute", &SimpleXmlNode::Attribute). Func("AttributeInt", &SimpleXmlNode::AttributeInt). ... Func("GetAttributeCount", &SimpleXmlNode::GetAttributeCount) Func("each", &SimpleXmlNode::each) ); 

But I don’t want the SimpleXmlNode class SimpleXmlNode know anything about these scripts and depend on extra modules.

  • one
    there are no methods in c ++ :) so the question is not correct :))) In C ++ there are functions of classes. you can go on the other side. Class functions differ from ordinary functions in that they have an implicit first argument that points to the object that called it. That is, you can create your own function, which will be the first argument to get a pointer to an object and slightly correct Func (or write your own). - KoVadim
  • @KoVadim read your comment and remembered that the scripting engine allows you to bind global functions as class methods, where the first argument is a pointer to an object. That's the way out! But this is not the answer to the original question. - zenden2k
  • make each function free. - Abyx

2 answers 2

My solution is not suitable for the general case.

So, with my limitations, I can only make each function free.

 namespace SimpleXmlExtend { SimpleXmlNode& each(SimpleXmlNode* pthis, Sqrat::Function callback) { pthis->each([&callback](int i, SimpleXmlNode& child) { Sqrat::SharedPtr<bool> res = callback.Evaluate<bool>(i, child); if (!!res && *res) { return true; } i++; return false; }); return *pthis; } } 

Fortunately, the scripting engine allows you to bind global functions as functions of a class, where the first argument is a pointer to an object:

 vm.GetRootTable().Bind("SimpleXmlNode", Class<SimpleXmlNode>(vm.GetVM(), "SimpleXmlNode"). Func("Attribute", &SimpleXmlNode::Attribute). GlobalFunc("each", SimpleXmlExtend::each) 

I had to add a function to the class:

 SimpleXmlNode& SimpleXmlNode::each(std::function<bool(int, SimpleXmlNode&)> callback) { int i = 0; TiXmlNode * child = 0; while ((child = impl_->m_el->IterateChildren(child)) != 0) { TiXmlElement* el = child->ToElement(); SimpleXmlNode node(el); bool res = callback(i, node); if (res ) { break; } i++; } return *this; } 

Now I can use a similar function call each both C ++ code and scripts.

    From the comment by @KoVadim :

    There are no methods in C ++. Therefore, the question is somewhat incorrect. In C ++, there are functions of classes.

    You can go on the other side. Class functions differ from ordinary functions in that they have an implicit first argument that indicates the object that called it. That is, you can create your own function, which receives the pointer to the object as the first argument, and correct Func (or write your own) a little.