I use LuaBridge to import a large framework of classes into a Lua-accessible framework. LuaBridge uses complex template functions that maintain a list of linkages back to methods and properties of each class. The Lua language itself is loosely typed, and it does not check to see if a method or property exists until you call it. My framework implements a ClassName method at every level that allows the Lua programs to know which class it is dealing with.
That's just background for my program. This is a C++ question. I would like to call a function that, in its broadest abstraction, looks something like this:
template <typename T>
do_something_in_lua(T * object); // LuaBridge will create a pointer to a T instance in Lua
and call it like this:
class foobase
{
public:
void notify_lua()
{ do_something_in_lua(this); }
};
class foo : public foobase
{
public:
int some_method();
};
foo x;
x.notify_lua();
My question is, is there a simple way for do_something_in_lua to use the maximally downcasted version of T? Either when I call it or in the templated function? Using dynamic_cast is difficult because I would have to maintain an explicit list of every possible subclass to find the right one. Even if it is adding a templated virtual function in foobase that returns the desired type of this, I would be interested in suggestions for an elegant solution.
I guess a broader version of my question would be, does modern C++ provide any tools for downcasting in template programming (e.g., in type_traits or the like) that I should be investigating?
Thanks to several helpful comments, the solution turns out to be a hybrid of CRTP and Double Dispatch. Here is a version of it based on my example above. I like the fact that it
requires no pure virtual functions
does not require templatizing the base class (for reasons specific to my code base)
If I ever need to add a new subclass, I just need to add it to the list in the std::variant, and better yet, the compiler will complain until I do so.
template <typename T>
void do_something_in_lua(T * object);
// every subclass of foobase must be listed here.
class foosub1;
class foosub2;
using foobase_typed_ptr = std::variant<foosub1*, foosub2*>;
class foobase
{
foobase_typed_ptr _typedptr;
public:
foobase(const foobase_typed_ptr &ptr) : _typedptr(ptr) {}
void notify_lua()
{
std::visit([](auto const &ptr)
{ do_something_in_lua(ptr); },
_typedptr);
}
};
class foosub1 : public foobase
{
public:
foosub1() : foobase(this) {}
int some_method1();
};
class foosub2 : public foobase
{
public:
foosub2() : foobase(this) {}
int some_method2();
};
// and to call it in code:
foosub2 x;
x.notify_lua(); // now Lua gets called with a foosub2* instead of a foobase*.
Related
From time to time I come across the following (or something like that) class hierarchy in different C++ projects:
class DummyBase
{
public:
virtual ~DummyBase() {}
virtual void doSomething() = 0;
};
template<typename T>
class Dummy : public DummyBase
{
public:
void doSomething() override
{
...
}
private:
T field;
};
Looks like as C++ idiom, pattern or maybe trick. Can you tell me the purpose of this contruction and what's the problem can be solved using it. I would be glad to read good articles or maybe books that describe it.
This is polymorphism based type erasure, it is often used for handling things like std::function or std::any which can store data of unrelated types in the exact same manner (e.g. function pointers and member function pointers for std::function).
A class Base, which I have no control over, has a function that accepts a member pointer to any class function. It is meant to be used as follows:
class Derived : public Base {
void bindProperties() {
Base::bindProperty("answer", &Derived::getAnswer);
}
int getAnswer() const { return 42; }
};
Some way (that I neither know nor care about), Base stores this pointer and later allows me to call Derived::get("answer") (of course, this is a simplified situation).
The down side is, that we tried to be smart in the past, and used multiple inheritance:
class ICalculator {
virtual int getAnswer() const;
};
template<class T>
class LifeAndUniverseCalculator : public T, public ICalculator {
virtual int getAnswer() const /* override */ { return 42; }
void bindProperties() {
T::bindProperty("answer", &ICalculator::getAnswer); // (*)
}
};
thinking that the multiple inheritance is not bad, as long as we only use it to inherit an interface and only have one "concrete" base class.
The templating is because sometimes we want to derive from Base and sometimes from one of its derived classes (which I also don't have access to) - if that is irrelevant you can pretend I wrote Base instead of T and drop the template.
Anyway, the problem I am having now, is that when I call
LifeAndUniverseCalculator calc;
calc.bindProperties();
int answer = calc.get("answer");
I get gibberish. I figured it may be something with pointers into vtables, so I tried replacing
T::bindProperty("answer", &ICalculator::getAnswer);
by
T::bindProperty("answer", &LifeAndUniverseCalculator::getAnswer);
hoping that it would calculate the offset correctly, but clearly that does not work (as you have figured out by now, I am really second guessing how this all works).
I thought of some options, such as
getting rid of the multiple inheritance and putting everything in ICalculator directly in LifeAndUniverseCalculator (it's the only derived class)
creating wrapper functions for all ICalculator stuff in LifeAndUniverseCalculator, e.g. LifeAndUniverseCalculator::Calculator_GetAnswer just calls ICalculator::GetAnswer.
I'd like to know
Preferably, is there a way to fix the line marked with (*) in a simple way?
If not, what is the best solution (one of the alternatives above, or something else)?
If I were able to contact the author of class Base and they would be willing and able to change their class, what specifically would I need to ask, if you are able to say something sensible based on my description.
If you need a MCVE, there is one which I think captures the problem on IDEOne.
In your MCVE, the function A::bindFunction (analogous to Base::bindProperty in your simplified code) force casts a member of function of B to a member function of A. This strikes me as the root problem. This can be fixed by changing the type of A::f to be an std::function<int(void)>:
class A
: public ABase {
public:
// int a, b;
class Unknown{};
typedef int(A::*Function)();
template<typename T, typename Func>
void bindFunction(T* owner, Func myf) {
f = std::bind(myf,owner);
}
int call() {
return f();
}
//Function f;
std::function<int(void)> f;
};
...
class Combined
: public A, public B {
public:
Combined(int value) : B(value), A() {}
virtual void /*A::*/bind() /* override */ {
A::bindFunction( this, &Combined::getValue );
}
};
With only this change, your MCVE works, printing out
The answer to Life, The Universe and Everything is 42
However, I recognize that the code that I changed belongs to a class that you've explicitly mentioned that you cannot modify. Is this indeed what Base does -- it casts member functions of other classes to member functions of itself? (Or perhaps, while my fix makes the code work, I've misidentified the problem).
When I use static polymorphism (CRTP), is there a nice way to give polymorphic methods their names?
template <class Derived>
struct Base
{
void interface()
{
// ...
static_cast<Derived*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
Derived::static_sub_func();
// ...
}
};
struct Derived : Base<Derived>
{
void implementation();
static void static_sub_func();
};
Because, as far as I know, interface and implementation can't have the same name (as they would if they were virtual). And that's kinda awkward, if class hierarchy is deep.
Maybe there is some nice way to deal with it? Or maybe I'm just wrong?
My approach would be to avoid inheritance (however cute CRTP feels), and use aggregation instead. A class template provides the interface, and is in turn provided a delegate class with the implementation. It would look something like this:
template <class Delegate>
struct Interface
{
void do_something()
{
// ...
delegate.do_something();
// ...
}
Delegate delegate;
};
This has the disadvantage that it's more awkward to supply constructor arguments to the delegate object, but that's not too difficult to manage.
When the parent class doesn't have any special functionality (as in a typical abstract interface), I can't see a reason why you can't reuse the function name in the child class. It will hide the parent method, but that doesn't matter because you're statically telling the compiler which version you wish to use.
However in your case it appears that you want the parent to do some work before and after calling the virtual method (smells like Template Method Pattern). In this case, regardless of whether you use runtime (virtual) or compile time (CRTP) polymorphism, you'll need to call your interface and implementation methods by alternate names.
If foo is the interface/template method in the base, then do_foo or foo_impl seem like perfectly reasonable names for the implementation functions regardless of runtime or compile time polymorphism.
After it turned out that what I originally wanted is probably not possible w/o involving C++11 I want to slightly change the requirement and ask you if this can be achieved.
previous question
Basically I want to check in compile time if a class is inheriting from "interface". By interface I mean class with pure virtual methods only.
I would like to do the following code:
template <typename T>
class Impl : public T {
public:
STATIC_ASSERT_INTERFACE(T);
};
The behavior here is if T has only pure virtual methods then it will compile and if one of its methods is not then fail.
Can anyone think of something like that?
This is basically similar to Java interfaces. In C++, there is no existence of interface as such, it's just a terminology used for a class with all pure-virtual methods and only static const data members.
Additionally, pure virtual methods may or may not have a function body. Thus C++ pure virtual methods are not exactly same as Java's abstract methods.
Unfortunately what you are asking is not possible to simulate in C++.
First off, interfaces are not really a native concept to C++. I'm sure most programmers know what they are, but the compiler doesn't, and that's where you're running into problems. C++ can do a lot of things, and I bet you can twist it into looking like a lot of different languages, but if you're going to write C++, it's best to do things the C++ way.
Another thing - there's a lot of grey area here. What if you had an "interface" like you suggested, but somebody did one of these:
// Technically not a member function, but still changes the behavior of that class.
bool operator==(const Interface &left, const Interface &right);
I'm almost 100% sure you can't stop someone from doing that.
You may be able to make sure there are no member variables though, even though I'm not sure I agree with this way of doing things. Make an empty class, and then do a static_assert(sizeof(InterfaceClass) == sizeof(Empty)). I'm not sure if it's safe to assume the size would be 0 - that's a question for someone more familiar with the standards.
What you want can not be done directly, as others have already explained.
However, you can still get the behavior you want with a bit of discipline from the interface developers. If all your interfaces derive from a common base class Interface, you can check that Interface is a base class at compile time using a technique similar to this question.
For example :
class Interface {
public :
virtual ~Interface() { }
};
template <typename T>
struct IsDerivedFromInterface {
static T t();
static char check(const Interface&);
static char (&check(...))[2];
enum { valid = (sizeof(check(t())) == 1) };
};
class MyInterface : public Interface {
public :
virtual void foo() = 0;
};
class MyBase {
public :
virtual void bar() { }
};
class Foo : public MyInterface {
public :
virtual void foo() { }
};
BOOST_STATIC_ASSERT(IsDerivedFromInterface<Foo>::valid); // just fine
class Bar : public MyBase {
public :
virtual void bar() { }
};
BOOST_STATIC_ASSERT(IsDerivedFromInterface<Bar>::valid); // oops
Of course, the developer of the base class can cheat and derive from Interface even though the base class is not an interface. Which is why I said it requires some discipline from the developer.
That said though, I can't see how this would be useful. I've never felt I needed this kind of compile time check.
I was not really sure how to formulate my question, but here is the puzzle I am trying to resolve:
if (config.a)
myObject = new Object<DummyInterface>();
else
myObject = new Object<RealInterface>();
so the task is to create a object with a dummy interface if it is specified in config, otherwise use real interface class.
How do I declare myObject then?
there are couple options, I could have Object class to derive from abstract class without templates: i.e.:
class Base
{
...
}
template <class T>
class Object : public Base
{
...
}
Then I could declare myObject as:
Base* myObject;
But here is the problem: what if my Object class declares a non virtual method:
template <class T>
class Object : public Base
{
public:
T getInterface() { return myInterface;}
private:
T myInterface;
}
I cannot call it like this:
myObject->getInterface()
and I cannot do dynamic cast, because I don't know the type until the runtime...
Any suggestions how to get around it? Maybe there is a another solution?
One way around is to use the visitor pattern. This way, your base class may implement a visit() method and your derived instances can override...
For example..
SomeComponent
{
template <typename T> // I'm being lazy here, but you should handle specific types
void handle(T& cInst)
{
// do something
}
};
class Base
{
public:
virtual void visit(SomeComponent& cComp) = 0;
};
template <class T>
class Object : public Base
{
public:
virtual void visit(SomeComponent& cComp)
{
cComp.handle(*this);
}
};
Now you can do this
SomeComponent c;
Base* obj = new Object<int>;
obj->visit(c);
And c will get the correct type.
if (config.a)
myObject = new Object<DummyInterface>();
else
myObject = new Object<RealInterface>();
This construction is incorrect in terms of the polymorphism.
Two template instantiations are two different classes. The best situation is when you have something like that:
template <class T> SomeClass: public SomeBaseClass
{
};
.........
SomeBaseClass* myObject;
But it brings you no profit.
The simplest and right solution is the virtual functions. The visitor pattern seems useful too.
I actually think that the visitor pattern would be misused here. Instead, this is a classic switch-on-types code smell that is best handled by polymorphism.
When you say "what if one derived class has an additional method to call", that is assuming a specific design. That is not a functional requirement. A functional requirement would be "what if one of the two objects created had to do behavior X during event Y". Why is this different? Because there are a number of ways to implement this that don't require more interface (though maybe more methods).
Let me show an example.
You have your factory
std::map<ConfigValue, Generator> objectFactory_;
That you've registered a bunch of generators for (probably in constructor of class)
RegisterGenerator(configValueA, DummyGenerator);
RegisterGenerator(configValueB, RealGenerator);
...
And at some point you want to create one of those objects.
shared_ptr<Base> GetConfigObject(ConfigFile config)
{
return objectFactory_[config.a]();
}
And then you want to use the object for handling an event, you can do
void ManagingClass::HandleEventA()
{
theBaseObjectReturned->HandleEventAThroughInterfaceObject(this);
}
Note how I passed a this pointer. This means if you have one object that doesn't want to do anything (like make that extra behavior call) that your managing class may provide, it doesn't need to use this.
Object<DummyInterface>::HandleEventAThroughInterfaceObject(ManagingClass *)
{
// just do dummy behavior
}
And then if you want to do something extra (call a new behavior) it can do it through that pointer in the RealInterface
Object<RealInterface>::HandleEventAThroughInterfaceObject(ManagingClass * that)
{
that->DoExtraBehavior();
// then dummy - or whatever order
// you could even call multiple methods as needed
}
That's the basic approach you should always take when dealing with polymorphism. You should never have two different code paths for different types except through calls to virtual dispatch. You should never have two different code blocks, one that calls methods A, B, and C and another that only calls A and D when dealing with a base object, depending on type. Instead, always make the derived objects do the work of figuring out what to do - because they know who they are. If you need to do stuff in the managing object, pass a this pointer for them to work with.