C++ Function pointer arguments and classes inheritance automatic cast - c++

First of all sorry if the name of the question is not clear enough. I really have no idea on how to call this problem.
So I have a function pointer inside a class that works like a java callback that I invoke with some parameters like itself that is derived from a parent class like in this example:
class Parent;
using f_Call = void(*)(Parent*);
class Parent
{
public:
void setCallback(f_Call call)
{
mOnCall = call;
}
protected:
f_Call mOnCall = nullptr;
};
class Child1 : Parent
{
public:
void doSomething()
{
// some work..
if (mOnCall)
mOnCall(this);
}
};
void onCallExe(Parent* p)
{
Child1* child = (Child1*)p;
// do some more work...
}
int main()
{
Child1 child;
child.setCallback(onCallExe);
child.doSomething();
}
My question is if does c++ has a way of doing the cast from parent to children automatically in onCallExe so I don't have to do it for every function I call.
Thank you!

Don't use function pointers. Instead, you want std::function<void()> (yes, without arguments) and pass it a lambda with a captured object.
using f_Call = std::function<void()>;
class Parent {
public:
void setCallback(f_Call call) {
mOnCall = call;
}
protected:
f_Call mOnCall;
};
class Child1 : public Parent {
public:
void doSomething() {
// some work..
if (mOnCall)
mOnCall(); // no argument!
}
};
int main() {
Child1 child;
child.setCallback([&child](){ /* do whatever with the child */ });
child.doSomething();
}
If you want, you can hide creation of the lambda in a function template.
template <class Obj, class CB>
void setCallback (Obj& obj, CB cb) {
obj.setCallback([&obj](){cb(obj);});
}
and then pass the global setCallback template any old function with a Child argument.
void onCallExe(Child1& child) {
// do some more work...
}
Child1 child;
setCallback(child, onCallExe);

Curiously recurring template pattern might be an option. However, you'll create separate base classes for each derived one, so you couldn't use them polymorphically – unless you provided a separate, common base. If the recurring template function overwrites a virtual one in the base, you might end up at where you wanted to get:
struct Base
{
virtual ~Base() { }
virtual void f() = 0;
};
template <typename T>
struct Intermediate : Base
{
void f() override
{
if(callback)
callback(static_cast<T*>(this));
}
void setCallback(void(*c)(T*))
{
callback = c;
}
private:
void(*callback)(T*) = nullptr;
};
struct Derived : Intermediate<Derived>
{
};
void g(Derived*) { }
void demo()
{
Derived d;
d.setCallback(g);
d.f();
}
(If you don't need polymorphism, you can skip Base class – then f doesn't have to be virtual either.)
Solely if you wanted to set the callbacks via pointer or reference to Base, you are a bit in trouble, as you cannot have virtual template member functions. You could, though provide a free-standing helper function:
template <typename T>
void setCallback(Base& b, void(*callback)(T*))
{
dynamic_cast<Intermediate<T>&>(b).setCallback(callback);
}
The dynamic cast will throw a std::bad_cast if b is of inappropriate type – unfortunately a rather costly run-time thing, a safe way to let the compiler determine if pointed/referred object is of correct type (usually) is not possible.

Related

Best approach for casting pointer to method from derived to base class

We have a base class ByteCode which is intended to be generic.
Children of ByteCode are expected to write methods of the form:
void m();
The ByteCode class should have a definition for method:
typedef void (ByteCode::*Method)();
In order to execute the bytecode, we have:
void exec() {
while (true) {
uint16_t opcode = getOpcode();
Method m = opcodes[opcode];
this->*m();
}
}
Doing this in one class would be no problem. But we have the generic code in the base class, and the derived has the array:
class MyByteCodeEngine : public ByteCode {
private:
static Method opcodes[65536];
void m1() {}
void m2() {}
void m3() {}
};
Method MyByteCodeEngine ::opcodes[65536] = {
MyByteCodeEngine::m1,
MyByteCodeEngine::m2,
MyByteCodeEngine::m3
}
The problem is that these methods are not base class, they are derived. But the only instance we have is derived, We don't want to incur the overhead of virtual, we just want to cast and make this work, but the compiler is catching every trick. If it would just trust us:
Method MyByteCodeEngine ::opcodes[65536] = {
(Method)MyByteCodeEngine::m1,
(Method)MyByteCodeEngine::m2,
(Method)MyByteCodeEngine::m3
}
We can solve this problem by eliminating the ByteCode class, but this forces us to repeat the code any time we have a bytecode interpreter. Any suggestions on how to fool C++ into accepting this, cleanly?
You can use the Curiously recurring template pattern so that the base class knows about the type of the member function.
template<class T>
struct ByteCode {
typedef void (T::* Method)();
void exec() {
while (true) {
uint16_t opcode = getOpcode();
Method m = T::opcodes[opcode];
static_cast<T*>(this)->*m();
}
}
};
class MyByteCodeEngine : public ByteCode<MyByteCodeEngine > {
private:
static Method opcodes[65536];
void m1() {}
void m2() {}
void m3() {}
};
MyByteCodeEngine::Method MyByteCodeEngine ::opcodes[65536] = {
&MyByteCodeEngine::m1,
&MyByteCodeEngine::m2,
&MyByteCodeEngine::m3
}

C++ compile time type determination

I have two classes deriving from the same base class. on compile time it is known which one gets created based on a macro define. I have another class that is a user and calls member functions (different ones for each class). It looks like this:
class User() {
void useClass( Base* p ) {
#ifdef useA
p->aFun();
#else
p->bFun()
#endif
}
class Base() {}
class A : public Base {
void aFun();
}
class B : public Base {
void bFun();
}
class C {
C() {
#ifdef useA
p = new A();
#else
p = new B();
#endif
}
Base* p;
User m_user;
void doStuffWithUser() {
user.useClass( p );
}
}
I would like to reduce the amount of macros, so I am wondering if there is a better way to do this. In particular, the #ifdef in the User class doesn't look very nice to me. Is there a way to reproduce it without using the macro? Ideally without runtime checks to determine what type p is.
EDIT:
The two derived classes have different members that need to be called and despite the inheritance, this cant be changed.
A solution is the visitor pattern.
The idea is to have two classes : the visitor and the visited.
The visitor is used to call a function depending on the real type of the object. The visited is the object of your class hierarchy.
In your example, you could do:
class User() {
void useClass( Base* p ) {
p->visit(visitor);
}
class Base() {
virtual void visit(Visitor) = 0;
}
class A : public Base {
void aFun();
virtual void visit(Visitor v) override {
v.visit(this);
}
}
class B : public Base {
void bFun();
virtual void visit(Visitor v) override {
v.visit(this);
}
}
class Visitor {
void visit(B* b) {
b->bFun();
}
void visit(A* a) {
a->aFun();
}
}
By having this double dispatch with the visit function, you ensure that you call the function depending on the real type.
I don't think there is a compile time solution to your issue because in useClass (as it is now), there is no way (at compile time) to know the real type of p. If you want to have a compile time solution you need to do more changes. For example making useClass a template or overloading it, which mean you can't call useClass with a Base* any more ...
The fact that A and B share a common base class is irrelevant since they have different interfaces that you are using.
I would make C a template and store a pointer to the derived class instead of the base class:
template<typename T>
class CT {
public:
CT() {
p = std::make_unique<T>();
}
std::unique_ptr<T> p;
User m_user;
void doStuffWithUser() {
user.useClass(p);
}
};
Then you can simply overload useClass() to accept either A or B:
class User {
public:
void useClass(A* p) {
p->aFun();
}
void useClass(B* p) {
p->bFun();
}
};
Now you just have one compile time switch:
#ifdef useA
using C = CT<A>;
#else
using C = CT<B>;
#endif
You can rename aFun and bFun to Fun and make it virtual(also add it in Base class) and in useClass, use Fun method, compiler will figure out which method to use.
This will eliminate first macro.
For the second maybe you should use rewrite it in some other way, so you wouldnt use macros at all. I don't think you can reproduce this behavior without macros.
Maybe you should have some flag that you give to constructor, 1 to create object A or 0 to create object B and get this flag from user at the runtime.
EDIT
So maybe you can create function Fun that in class A calls aFun and in class B calls bFun.
You can create a template for User class and specialize it for class A and class B:
template<typename T>
class User
{
void useClass( Base* p );
}
template<>
class User<A>
{
void useClass( Base* p ) {p->aFun();}
};
template<>
class User<B>
{
void useClass( Base* p ) {p->bFun();}
};
Now in class C:
template<typename T>
class C {
C() {
p = new T();
}
Base* p;
User<T> m_user;
void doStuffWithUser() {
m_user.useClass( p );
}
}
As a final note, just avoid using new operator. Try std::unique_ptr or std::shared_prt
PS. I have not tested this code
if you do not want to change any interface you can use single #ifdef
class Base {};
class A : public Base {
public:
void aFun(){}
};
class B : public Base {
public:
void bFun(){}
};
#ifdef useA
typedef A impl_type;
auto correct_func = &impl_type::aFun;
#else
typedef B impl_type;
auto correct_func = &impl_type::bFun;
#endif
class User {
public:
void useClass( Base* p ) {
auto pointer = (static_cast<impl_type*>(p));
(pointer->*correct_func)();
}
};
class C {
C() {
p = new impl_type();
}
Base* p;
User m_user;
void doStuffWithUser() {
m_user.useClass( p );
}
};
Probably you could name both functions with the same name in A and B and make it virtual, so useClass will call only needed function.
Like
class User() {
void useClass( Base* p ) {
p->fun();
}
};
class Base() {
virtual void fun() = 0;
};
class A : public Base {
void fun();
};
class B : public Base {
void fun();
};
Also you can use some kind of constexpr function (if you are using c++11 standard or newer) to determine what type p is.
Edit:
After seeing comment, i think that you're probably can left yours aFun(), bFun(), and just add some fun() func which will be derived and call type-specific function.
Also, it may be helpful to try and create some adapter classes with same interfaces(as in gof patterns).
Edit2: I mean that there could be some function like
constexpr Base* chooseType(int a){
if(a == 0){
return new A();
} else {
return new B();
}
}
/////
C() {
int case = 0;
p = chooseType(case);
}
And it will be called in compile-time, so as choice of class.
If you can't change the interface, want to get rid of #ifdefs, and have compile-time guarantee of types being used, without run-time checks - I would suggest using combination of templates, and overloaded functions.
First of all, I would change class C to be a template:
template<typename Type>
class C
{
static_assert(std::is_base_of<Base, Type>::value, "Template argument of C is not base of Base!");
public:
C () {p = new Type;}
~C() {delete p;}
void fun () {u.useClass (p);}
private:
Type* p;
User u;
};
And, then would change User class to switch between different possible implementations of Base with overloaded functions:
class User
{
public:
void useClass (A* p) {p->aFun();}
void useClass (B* p) {p->bFun();}
};
And, then you would create object of C as follows:
C<A> ca;
If you forgot to implement type-specific useClass, or tried to use wrong type in C (i.e. not inherited from Base), you would get compile-time errors.
In addition, if some of the child classes of Base, that you want to switch between, have non-default constructors, you may pass a functor (e.g. std::function<Type*()>) to a C constructor, and use that to create an object.
Such a constructor may look like:
C (std::function<Type* ()> function) {p = function();}
And usage of it would look like:
C<Z> cz ([&]{return new Z(someInt);});

How to automatically call a method or generate code if a subclass derived from a base class?

I have some classes that describe abilities / behaviours, such as flying, or driving etc. Each of these classes has a specific method that must be called to load some data - For example, Flyable has loadFlyData(), Drivable has loadDriveData(). For each class the method name is unique.
I have many derived classes that may inherit from one or more of these behaviour classes. Each of these derived classes has a method called loadData(), in which we should call all the parent behaviour classes methods such as loadFlyData(), loadDriveData() etc.... Is there a way to automatically generate this method using metaprogramming ? Since there are many derived classes, it may be more maintainable if I can generate these methods using metaprogramming...
Behaviour classes : (An object class may have any of these behaviours, and will have to call that classes "load" method...
class Flyable {
void loadFlyData() {
}
};
class Drivable{
void loadDriveData() {
}
};
All object classes derive from Object:
class Object {
virtual void loadData() {
}
};
A derived class:
class FlyingCar : public Object, public Flyable, public Drivable {
virtual void loadData() override {
// How to automatically generate code so that the next two lines are called:
loadFlyData();
loadDriveData();
}
};
Sure is possible. You'll need however to employ some conventions so the code can be generic. See it live.
#include <iostream>
using namespace std;
struct Flyable{
int loadConcreteData(){
cout << "Flyable\n"; return 0;
}
};
struct Drivable{
int loadConcreteData(){
cout << "Drivable\n"; return 0;
}
};
class Object{
virtual void loadData(){
}
};
template<class ...CS>
struct ConcreteLoader : Object, CS... {
void loadData() override {
int load[] = {
this->CS::loadConcreteData()...
};
}
};
class FlyingCar : public ConcreteLoader<Flyable,Drivable>{
};
int main() {
FlyingCar fc;
fc.loadData();
return 0;
}
Changes that need mentioning:
The return type of each concrete Load function had to be changed. This is to facilitate the "array trick" in expanding the parameter pack.
The names of all the load functions are the same, again for the same reason.
Reason (1) may become obsolete once c++17 and fold expressions roll out.
You can make a free function loadXData() that will become a noop if your class isn't X:
namespace detail
{
void loadFlyData(Flyable* ptr) { ptr->loadFlyData(); }
void loadFlyData(...) {}
void loadDriveData(Drivable* ptr) { ptr->loadDriveData(); }
void loadDriveData(...) {}
}
class FlyingCar : public Object, public Flyable, public Drivable{
public:
virtual void loadData()override{
//How to automatically generate code so that the next two lines are called:
detail::loadFlyData(this);
detail::loadDriveData(this);
}
};
demo
Though I think using a common name loadData and just calling it for all variadic parents might be preferable:
template<typename... Policies>
struct ComposedType : Object, Policies...
{
virtual void loadData() override {
int arr[] = {
((void)Policies::loadData(), 0)...
};
(void)arr;
}
};
using FlyingCar = ComposedType<Drivable, Flyable>;
demo
The above loadData could be simplified in C++1z:
virtual void loadData() override {
((void)Policies::loadData(), ...);
}
demo

C++ Templated Virtual Function

Templated virtual member functions are not supported in C++ but I have a scenario where it would be ideal. Im wondering if someone has ideas for ways to accomplish this.
#include <iostream>
class Foo {
public:
virtual void bar(int ){}
// make a clone of my existing data, but with a different policy
virtual Foo* cloneforDB() = 0;
};
struct DiskStorage {
static void store(int x) { std::cout << "DiskStorage:" << x << "\n"; }
};
struct DBStorage {
static void store(int x) { std::cout << "DBStorage:" << x << "\n"; }
};
template<typename Storage>
class FooImpl : public Foo {
public:
FooImpl():m_value(0) {}
template<typename DiffStorage>
FooImpl(const FooImpl<DiffStorage>& copyfrom) {
m_value = copyfrom.m_value;
}
virtual void bar(int x) {
Storage::store(m_value);
std::cout << "FooImpl::bar new value:" << x << "\n";
m_value = x;
}
virtual Foo* cloneforDB() {
FooImpl<DBStorage> * newfoo = new FooImpl<DBStorage>(*this);
return newfoo;
}
int m_value;
};
int main()
{
Foo* foo1 = new FooImpl<DiskStorage>();
foo1->bar(5);
Foo* foo2 = foo1->cloneforDB();
foo2->bar(21);
}
Now if I want to clone the Foo implmemetation, but with a different Storagepolicy, I have to explicitly spell out each such implementation:
cloneforDB()
cloneforDisk()
A template parameter would have simplified that.
Can anyone think of a cleaner way to do this?
Please focus on the idea and not the example, since its obviously a contrived example.
Usually if you want to use a virtual template method, it means that something is wrong in the design of your class hierarchy. The high level reason for that follows.
Template parameters must be known at compile-time, that's their semantics. They are used to guarantee soundness properties of your code.
Virtual functions are used for polymorphism, ie. dynamic dispatching at runtime.
So you cannot mix static properties with runtime dispatching, it does not make sense if you look at the big picture.
Here, the fact that you store something somewhere should not be part of the type of your method, since it's just a behavioral trait, it could change at runtime. So it's wrong to include that information in the type of the method.
That's why C++ does not allow that: you have to rely on polymorphism to achieve such a behavior.
One easy way to go would be to pass a pointer to a Storage object as an argument (a singleton if you just want one object for each class), and work with that pointer in the virtual function.
That way, your type signature does not depend on the specific behavior of your method. And you can change your storage (in this example) policy at runtime, which is really what you should ask for as a good practice.
Sometimes, behavior can be dictated by template parameters (Alexandrescu's policy template parameters for example), but it is at type-level, not method level.
Just use templates all the way:
class Foo {
public:
virtual void bar(int ){}
template <class TargetType>
Foo* clonefor() const;
};
class FooImpl { ... };
template
inline <class TargetType>
Foo* Foo::clonefor() const
{
return new FooImpl<TargetType>(*this);
}
Now call it:
int main()
{
Foo* foo1 = new FooImpl<DiskStorage>();
foo1->bar(5);
Foo* foo2 = foo1->clonefor<DBStorage>();
foo2->bar(21);
}
A trick I have sometimes used to get around this issue is this:
template<typename T>
using retval = std::vector<T const*>;
struct Bob {};
// template type interface in Base:
struct Base {
template<typename T>
retval<T> DoStuff();
virtual ~Base() {};
// Virtual dispatch so children can implement it:
protected:
virtual retval<int> DoIntStuff() = 0;
virtual retval<double> DoDoubleStuff() = 0;
virtual retval<char> DoCharStuff() = 0;
virtual retval<Bob> DoBobStuff() = 0;
};
// forward template interface through the virtual dispatch functions:
template<> retval<int> Base::DoStuff<int>() { return DoIntStuff(); }
template<> retval<double> Base::DoStuff<double>() { return DoDoubleStuff(); }
template<> retval<char> Base::DoStuff<char>() { return DoCharStuff(); }
template<> retval<Bob> Base::DoStuff<Bob>() { return DoBobStuff(); }
// CRTP helper so the virtual functions are implemented in a template:
template<typename Child>
struct BaseHelper: public Base {
private:
// In a real project, ensuring that Child is a child type of Base should be done
// at compile time:
Child* self() { return static_cast<Child*>(this); }
Child const* self() const { return static_cast<Child const*>(this); }
public:
virtual retval<int> DoIntStuff() override final { self()->DoStuff<int>(); }
virtual retval<double> DoDoubleStuff() override final { self()->DoStuff<double>(); }
virtual retval<char> DoCharStuff() override final { self()->DoStuff<char>(); }
virtual retval<Bob> DoBobStuff() override final { self()->DoStuff<Bob>(); }
};
// Warning: if the T in BaseHelper<T> doesn't have a DoStuff, infinite
// recursion results. Code and be written to catch this at compile time,
// and I would if this where a real project.
struct FinalBase: BaseHelper<FinalBase> {
template<typename T>
retval<T> DoStuff() {
retval<T> ret;
return ret;
}
};
where I go from template-based dispatch, to virtual function dispatch, back to template based dispatch.
The interface is templated on the type I want to dispatch on. A finite set of such types are forwarded through a virtual dispatch system, then redispatched at compile time to a single method in the implementation.
I will admit this is annoying, and being able to say "I want this template to be virtual, but only with the following types" would be nice.
The reason why this is useful is that it lets you write type-agnostic template glue code that operates on these methods uniformly without having to do stuff like pass through pointers to methods or the like, or write up type-trait bundles that extract which method to call.

How can 2 different classes point to the same datatable name

I need to initialize an object in a method without specifying the class from where the object is. Can I do that?
can someone give me an example?
EDIT:
MyClass{
...};
MySecondClass
{...
};
void method(*object); //how to write correct??
{..}
MyClass *x= new MyClass();
MySecondClass *y= new MySecondClass();
method(x);
method(y);
Use templates.
template <typename T>
void method(T* object) {
// do stuff with the object, whose real type will be substituted for `T`
}
Templates are a bit complex, so read the chapter in your C++ book on them for more information.
It sounds like you're looking for an interface. You would define an interface that fits the needs of whatever it is that your method is doing.
class MyInterface
{
public:
virtual void doSomething1() = 0;
virtual void doSomething2() = 0;
};
class MyObject : public MyInterface
{
public:
void doSomething1()
{
// Code here
}
void doSomething2()
{
// Code here
}
};
It's somewhat unclear exactly the situation you have b/c you haven't shown any code, but make the method you want to call part of a class. (if it isn't already)
class ClassWithMethod
{
public:
ClassWithMethod(MyInterface &myI)
:x(myI)
{
}
void methodYouUseInjectedObject()
{
// Code
x.doSomething1();
// More code
}
private:
MyInterface &x;
};
Then in you application code where you instantiate the ClassWithMethod, you would "inject" the concrete type of the object you want called.
int main(int argc, char *argv[])
{
MyObject myObject;
ClassWithMethod classMethod(myObject);
// Call the method that will use the injected object.
classMethod.methodYouUseInjectedObject();
return 1;
}
EDIT: (based on updated question)
If you want to create a method that can take two different (and unrelated) objects, but the use the same method signatures you can use a template.
class ClassWithMethod
{
public:
template <class T>
void methodYouUseInjectedObject(T object)
{
T.doSomething();
}
};
This is similar to my approach above except that you do not need to derive your different objects off an interface.
You can use a template.
template<typename T>
void method(T object) {
object.doSomething()
}