Invoking a method from stored class reference - c++

I am working on a callback template class where the callback isn't function or functor but a class reference. Depending on the context, the callback is invoked by calling specific method from registered class, roughly implemented as follows:
template<typename T>
class callback
{
public:
// ctors, moves, copies, assignments, ...
template<typename F, typename ... A>
void invoke(F method_ptr, A ... args)
{
(*m_interface_ptr.*method_ptr)(std::forward<A>(args) ...);
}
private:
T * m_interface_ptr;
};
Now, the usage of such template looks something like this:
struct intf
{
virtual void method_a() { ... }
virtual void method_b(int n) { ... }
};
intf i;
callback<intf> c;
c.subscribe(i);
c.invoke(&intf::method_a);
c.invoke(&intf::method_b, 7);
This code works just fine, but the part where I am calling a method from class reference feels a bit odd. Trouble comes if I try to extend the callback class to support both class reference callbacks and functor or plain function callbacks.
Is there a standard way of storing the class reference and invoking methods on it? Something like std::function but supporting my case.
Usecase #1: Calling a method from stored class reference
intf i;
// Create some std:: reference wrapper which allows custom method calls by name
std::some_ref_callable ri(i);
// Pass into callback and invoke
callback<std::some_callable<intf>> ci(ri);
ci.invoke(&intf::method_b, 7);
Usecase #2: Calling a lambda
auto l = []{ /* generic lambda */ };
callback<decltype(l)> cf(l);
cf.invoke();
Usecase #3: Calling a plain function
void func(int n){ /* plain function with param */ }
callback<decltype(func)> cf(func);
cf.invoke(1337);
Possible custom implementation would look something like this:
template<typename T>
struct some_ref_callable
{
template<typename R, typename ... A>
auto operator ()(R(T:: * method_ptr)(A ...), A ... args)
{
return (*m_object_ptr.*method_ptr)(std::forward<A>(args) ...);
}
T * m_object_ptr = nullptr;
};

Related

C++/(Qt) pointer to any object with specific method

How do I do to call a specific method present on all classes from an other (TranslationManager) class ?
I simplified a lot the code. I just want to call the setTranslationText of any class from TranslationManager.
These are to take in consideration:
All classes have a setTranslationText method
We should call setTranslationText of any class from TranslationManager by using the pointer to the class
class Interface
{
...
public:
void setTranslationText(QString translatedString);
}
class AnyOtherInterface
{
...
public:
void setTranslationText(QString translatedString);
}
...
…
Translationmanager::Translationmanager(){
AnyClass = Interface; // Pointer to Interface Class
AnyClass->setTranslatioNText("Text");
AnyClass = AnyOtherInterface; // Pointer to AnyOtherInterface Class
AnyClass->setTranslatioNText("AnotherText");
}
…
You could use a template
template <typename T>
void setTranslationText(T* t, const QString &translatedString)
{
t->setTranslationText(translatedString);
}
That way you wouldn't need an interface class just to inherit for this one (or however many) methods. Then the template would only compile if for a given class instantiation they had a setTranslationText method defined. The way you'd use it is
Translationmanager::Translationmanager()
{
setTranslationText(Interface, "Text"); // Pointer to Interface Class
setTranslationText(AnyOtherInterface, "AnotherText"); // Pointer to AnyOtherInterface Class
}
Adding to Cory's answer: If you're using C strings to initialize QString, you shouldn't depend on the implicit conversion - instead, make your use case explicit:
template <typename T>
void setTranslationText(T* t, const char *translatedString) {
t->setTranslationText(QString::fromUtf8(translatedString));
}
I wasn't precise about what I wanted. I finally found the best solution to my problem: callback.
Solution found on: C++ class member callback simple examples
std::vector<std::function<void(std::string,std::string)>> callbacks;
template<class T> void addTranslationText(T* const object, void(T::* const mf)(std::string,std::string)){
using namespace std::placeholders;
callbacks.emplace_back(std::bind(mf, object, _1, _2));
}
...
// Call callback
callbacks.at(0)(std::string("arg1"), std::string("arg2"));

How to store arbitrary method pointers in c++11?

I need a way to store a list of method pointers, but I don't care about what class they belong to. I had this in mind:
struct MethodPointer
{
void *object;
void (*method)(void);
};
Then I could have have a function which takes an arbitrary method:
template <typename T>
void register_method(void(T::*method)(void), T* obj) {
MethodPointer pointer = {obj, method);
}
void use_method_pointer() {
...
MethodPointer mp = ...
// call the method
(mp.object->*method)();
...
}
This obviously doesn't compile because I can't convert the method pointer into a function pointer in register_method().
The reason I need this is because I have a class which can emit events - and I want arbitrary instances to subscribe to these events as method calls. Is this possible to do?
PS. Conditions apply:
1. I don't want to use Boost
2. I don't want to use a 'Listener' interface, where a subscriber have to subclass an abstract interface class.
Thank you for your time.
I believe you are just looking for std::function:
using NullaryFunc = std::function<void()>;
Registration:
template <typename T>
void register_method(void(T::*method)(void), T* obj) {
NullaryFunc nf = std::bind(method, obj);
// store nf somewhere
}
Usage:
void use_method() {
...
NullaryFunc nf = ...;
// call the function
nf();
...
}

Convert C++ function pointer to c function pointer

I am developing a C++ application using a C library. I have to send a pointer to function to the C library.
This is my class:
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private:
Ui::MainWindow *ui;
void f(int*);
private slots:
void on_btn_clicked();
};
This is my on_btn_clicked function:
void MainWindow::on_btn_clicked()
{
void (MainWindow::* ptfptr) (int*) = &MainWindow::f;
c_library_function(static_cast<void()(int*)>(ptfptr), NULL);
}
The C function should get a pointer to a such function : void f(int*).
But the code above doesn't work, I cannot succeed to convert my f member function to the desired pointer.
Can anybody please help?
You can't pass a non-static member function pointer as an ordinary function pointer. They're not the same thing, and probably not even the same size.
You can however (usually) pass a pointer to a static member function through C. Usually when registering a callback in a C API, you also get to pass a "user data" pointer which gets passed back to your registered function. So you can do something like:
class MyClass
{
void non_static_func(/* args */);
public:
static void static_func(MyClass *ptr, /* other args */) {
ptr->non_static_func(/* other args */);
}
};
Then register your callback as
c_library_function(MyClass::static_func, this);
i.e. pass the instance pointer to the static method, and use that as a forwarding function.
Strictly speaking for total portability you need to use a free function declared extern "C" rather than a static member to do your forwarding (declared as a friend if necessary), but practically speaking I've never had any problems using this method to interface C++ code with GObject code, which is C callback-heavy.
You can't pass a function pointer to a non-static member function. What you can do is to create a static or global function that makes the call with an instance parameter.
Here's an example I find useful which uses a helper class with two members: a function wrapper and a callback function that calls the wrapper.
template <typename T>
struct Callback;
template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
template <typename... Args>
static Ret callback(Args... args) { return func(args...); }
static std::function<Ret(Params...)> func;
};
// Initialize the static member.
template <typename Ret, typename... Params>
std::function<Ret(Params...)> Callback<Ret(Params...)>::func;
Using this you can store any callable, even non-static member functions (using std::bind) and convert to a c-pointer using the Callback::callback function. E.g:
struct Foo {
void print(int* x) { // Some member function.
std::cout << *x << std::endl;
}
};
int main() {
Foo foo; // Create instance of Foo.
// Store member function and the instance using std::bind.
Callback<void(int*)>::func = std::bind(&Foo::print, foo, std::placeholders::_1);
// Convert callback-function to c-pointer.
void (*c_func)(int*) = static_cast<decltype(c_func)>(Callback<void(int*)>::callback);
// Use in any way you wish.
std::unique_ptr<int> iptr{new int(5)};
c_func(iptr.get());
}
If I recall it correctly, Only static methods of a class can be accessed via "normal" C pointer to function syntax. So try to make it static. The pointer to a method of a class needs extra information, such as the "object" (this) which has no meaning for a pure C method.
The FAQ shown here has good explanation and a possible (ugly) solution for your problem.
#Snps answer is great. I extended it with a maker function that creates a callback, as I always use void callbacks without parameters:
typedef void (*voidCCallback)();
template<typename T>
voidCCallback makeCCallback(void (T::*method)(),T* r){
Callback<void()>::func = std::bind(method, r);
void (*c_function_pointer)() = static_cast<decltype(c_function_pointer)>(Callback<void()>::callback);
return c_function_pointer;
}
From then on, you can create your plain C callback from within the class or anywhere else and have the member called:
voidCCallback callback = makeCCallback(&Foo::print, this);
plainOldCFunction(callback);
#Snps answer is perfect! But as #DXM mentioned it can hold only one callback. I've improved it a little, now it can keep many callbacks of the same type. It's a little bit strange, but works perfect:
#include <type_traits>
template<typename T>
struct ActualType {
typedef T type;
};
template<typename T>
struct ActualType<T*> {
typedef typename ActualType<T>::type type;
};
template<typename T, unsigned int n,typename CallerType>
struct Callback;
template<typename Ret, typename ... Params, unsigned int n,typename CallerType>
struct Callback<Ret(Params...), n,CallerType> {
typedef Ret (*ret_cb)(Params...);
template<typename ... Args>
static Ret callback(Args ... args) {
func(args...);
}
static ret_cb getCallback(std::function<Ret(Params...)> fn) {
func = fn;
return static_cast<ret_cb>(Callback<Ret(Params...), n,CallerType>::callback);
}
static std::function<Ret(Params...)> func;
};
template<typename Ret, typename ... Params, unsigned int n,typename CallerType>
std::function<Ret(Params...)> Callback<Ret(Params...), n,CallerType>::func;
#define GETCB(ptrtype,callertype) Callback<ActualType<ptrtype>::type,__COUNTER__,callertype>::getCallback
Now you can just do something like this:
typedef void (cb_type)(uint8_t, uint8_t);
class testfunc {
public:
void test(int x) {
std::cout << "in testfunc.test " <<x<< std::endl;
}
void test1(int x) {
std::cout << "in testfunc.test1 " <<x<< std::endl;
}
};
cb_type* f = GETCB(cb_type, testfunc)(std::bind(&testfunc::test, tf, std::placeholders::_2));
cb_type* f1 = GETCB(cb_type, testfunc)(
std::bind(&testfunc::test1, tf, std::placeholders::_2));
f(5, 4);
f1(5, 7);
The short answer is: you can convert a member function pointer to an ordinary C function pointer using std::mem_fn.
That is the answer to the question as given, but this question seems to have a confused premise, as the asker expects C code to be able to call an instance method of MainWindow without having a MainWindow*, which is simply impossible.
If you use mem_fn to cast MainWindow::on_btn_clicked to a C function pointer, then you still a function that takes a MainWindow* as its first argument.
void (*window_callback)(MainWindow*,int*) = std::mem_fn(&MainWindow::on_btn_clicked);
That is the answer to the question as given, but it doesn't match the interface. You would have to write a C function to wrap the call to a specific instance (after all, your C API code knows nothing about MainWindow or any specific instance of it):
void window_button_click_wrapper(int* arg)
{
MainWindow::inst()->on_btn_clicked(arg);
}
This is considered an OO anti-pattern, but since the C API knows nothing about your object, it's the only way.
I've got an idea (not entirely standard-compliant, as extern "C" is missing):
class MainWindow;
static MainWindow* instance;
class MainWindow
{
public:
MainWindow()
{
instance = this;
registerCallback([](int* arg){instance->...});
}
};
You will have problems if multiple instances of MainWindow are instantiated.

Template function having its caller's context?

Consider the following code snippet.
template <T>
MyPtr<T> CreateObject()
{
// Do something here first...
// return our new object
return MyPtr<T>(new T());
}
class Foo
{
private:
Foo() { }
public:
static MyPtr<Foo> GetNewInstance()
{
// ERROR: Foo is private...
return CreateObject<Foo>();
}
};
class Bar
{
public:
Bar() { }
};
int main()
{
MyPtr<Bar> bar = CreateObject<Bar>();
return 0;
}
Without resorting to macro for CreateObject (I like the syntax of MyPtr<type> obj = CreateObject<type>(params)), is there a way to make the function CreateObject share the same context as the caller function, thus able to access private Foo c'tor? 'friend' is not what I'm looking for as it would mean anyone calling CreateObject would have access to private Foo c'tor, which is not what I want. Overloading the new operator wouldn't work either as it is imperative that a MyPtr is returned instead of just T* (by assigning T* to MyPtr assigns a type to the object that is required somewhere else).
I guess what I'm looking for is something in between a macro and a template function (syntax of a template function but gets expanded fully like a macro). It would be quite useful to have this feature in this particular case.
Well, you could do that with the passkey pattern:
template<class T, class PassKey>
MyPtr<T> CreateObject(PassKey const& key)
{
return new T(key);
}
class FooKey{
private:
FooKey(){} // private ctor
FooKey(const FooKey&); // undefined private copy ctor
friend class Foo;
};
class Foo{
public:
// public ctor
Foo(FooKey const&){}
static MyPtr<Foo> GetNewInstance()
{
return CreateObject<Foo>(FooKey());
}
};
Example at Ideone.
With C++0x, this can be done much easier than creating a new Key struct every time, since template parameters are now allowed to be friends:
template<class T>
struct PassKey{
private:
PassKey(){}
PassKey(const PassKey<T>&);
friend T;
};
This is basically the same as attempting to use make_shared with a private constructor.
The only way to allow this is with friend. You're pretty much stuck in this case I'm afraid.
I am not sure as to what you are trying to achieve. The simplification to post the problem here has taken away the actual need for the whole thing. So I will just assume that you know what you are doing, and that you really need this (and I suggest that you rethink whether you do need it, as I don't see a point...)
At any rate, you can solve the problem by passing a creator callback to the CreateObject template:
template <typename T, typename Creator>
MyPtr<T> CreateObject( Creator creator )
{
// Do something here first...
return MyPtr<T>(creator());
}
class Foo
{
private:
Foo() {}
static Foo* create() { return new Foo(); }
public:
static MyPtr<Foo> GetNewInstance() {
return CreateObject<Foo>( &Foo:create );
}
// ...
};
The actual issue though, is what does Do something here first actually does that forces you into this complex creation patterns. The fact that it has to be executed before the creation of the new object seems to indicate that there are hidden dependencies not shown in the code, and that usually end up in maintenance nightmares, where someone down the line reorders some code, or adds a new constructor and everything seems to fall apart. Revisit your design and consider whether those dependencies can be simplified or made explicit.
Since you are newing up the object in the very end it really doesn't relate to your CreateObject function. So Change the function prototype to:
template <typename T>
MyPtr<T> CreateObject(T* const p)
{
//...
return MyPtr<T>(p);
}
Usage:
static MyPtr<Foo> GetNewInstance()
{
return CreateObject(new Foo());
}
is there a way to make the function CreateObject share the same context as the caller function
Yes, pass the context you need as an argument (either as an argument to the template, or as an argument to the function).
In practice, move the new T call to a separate function (or struct template, as I chose to do here), like this:
// Dummy representation of your pointer type
template <typename T>
struct MyPtr
{
MyPtr( T *p ) { }
};
// Default constructor template; may be specialized to not use "new" or so.
template <typename T>
struct Constructor
{
static T *invoke() { return new T; }
};
// Needs to be a struct (or class) so 'C' can have a default value
template <typename T, typename C = Constructor<T> >
struct CreateObject
{
MyPtr<T> operator()() {
return MyPtr<T>( C::invoke() );
}
};
class Foo
{
private:
friend struct Constructor<Foo>;
Foo() { }
public:
static MyPtr<Foo> GetNewInstance()
{
return CreateObject<Foo>()();
}
};
If you want to handle different constructor signatures (read: if not all types T have the same constructor signature), you could also choose to not pass the Constructor as a template to the CreateObject struct, but instead use a function argument. That way, you could 'load' a Constructor like this:
// ...
static MyPtr<Foo> GetNewInstance()
{
Constructor<Foo> c( arg1, arg2, arg3 );
return CreateObject<Foo>( c );
}

C++ member function applied to object

I want to call member function by passing it as template parameter, without using boost is possible. Here is an example off what I tried to do,
class object { void method(); }
{
object object_instance;
...
apply<object:: method>();
...
template<class F>
void apply() { F(object_instance); } // want to call object_instance.F()
}
that does not work, so question is how do I go about binding object method to an object.
Thanks
above is an example, not the real code. I have a bunch of functions differing only in name, but with many parameters, that I want to wrap around in operators.
Something like:
struct foo
{
void bar(void) {}
};
template <typename R, typename C>
R apply(C& pObject, R (C::*pFunc)())
{
return (pObject.*pFunc)();
}
int main(void)
{
foo f;
apply(f, &foo::bar);
}
this.
This is similar to your code, and will allow passing a member function as a template parameter:
class object { public: void method() {} };
object object_instance;
template<void (object::*F)()>
void apply() {
(object_instance.*F)();
}
int main() {
apply<&object::method>();
return 0;
}
As a member function isn't a type or integral value, you can't pass it as a template parameter. You could do what you seem to want by creating a struct which calls the member function, though having object_instance in scope in the template is rather smelly.
What are you actually trying to do?
This example is for rvalue references in c++ox. Does not work on all compilers.
class Sample
{
public:
void fun() { cout << "Sample::fun\n"; }
};
template<typename Function>
void FunCall( Function&& f)
{
f();
}
void RvaluesDemo()
{
FunCall([&]
{
Sample().fun();
});
}