Passing a member name as argument - c++

I am trying to pass a member of class as argument to a function (not member method). The simple example of my intention would be like this.
template <typename ObjType>
void myOutput(ObjType* obj, ????)
{
std::cout << obj->???? << std::endl;
}
struct A
{
int a;
};
struct B
{
std::string b;
};
int main()
{
A A1;
B B1;
A1.a = 1;
B1.b = "something";
myOutput(&A1, A1::a);
myOutput(&B1, B1::b);
return 0;
}
So my question is what should i replace "????" with? I am not using C++11.
Thanks.
EDIT:
To clarify my intentions. The function myOutput doesn't really know the name of my member, and i do not want to use a function like memberToString() or something.
So the output should look like this for first call.
void myOutput(A* obj, ????)
{
std::cout << obj->a << std::endl;
}
and for the second
void myOutput(B* obj, ????)
{
std::cout << obj->b << std::endl;
}

If you know the member name at compile time, you can use a member pointer to refer to the member.
template <typename ObjType, typename MembType>
void myOutput(ObjType* obj, MembType memb)
{
std::cout << obj->*memb << std::endl;
}
This can then be called as such:
myOutput(&A1, &A::a);
myOutput(&B1, &B::b);
Naturally, you should ask yourself why it is you want to do this, and if it wouldn't be possible to simply pass A1->a or B1->b directly into the function as a single argument, instead.

Related

Selecting ambiguous constructor manually

When a call to a function (member class function or free function) is ambiguous, we can select it easily using static_cast<> to the function type we calling:
struct S {
void f(uint32_t, uint8_t) {
std::cout << "1\n";
}
void f(uint32_t, uint32_t) {
std::cout << "2\n";
}
};
int main() {
S s;
auto f1 = static_cast<void(S::*)(uint32_t, uint8_t)>(&S::f);
(s.*f1)(1,1);
auto f2 = static_cast<void(S::*)(uint32_t, uint32_t)>(&S::f);
(s.*f2)(1,1);
}
But I wonder if it is possible to do something similar for constructors. For example, in the following structure:
struct S {
S(uint32_t, uint8_t) {
std::cout << "1\n";
}
S(uint32_t, uint32_t) {
std::cout << "2\n";
}
};
Is it possible to manually solve ambiguous constructor call for creating S s(1,1);?
Is this what you had in mind?
S s1(static_cast<uint32_t>(1), static_cast<uint32_t>(2));
S s2(static_cast<uint32_t>(1), static_cast<uint8_t>(2));
This disambiguates the constructor-calls by specifying the types explicitly in the arguments.
Why don't just cast to the correct type? 1 is an int literal so it makes some "confusion" when passing to unsigned parameters
int main() {
S s;
s.f(1, (uint8_t)1);
s.f(1, (uint32_t)1);
s.f(1, 1U);
}
Demo on Godlbolt

Lambda as "member" when class instance is captured

The question title might not be the most clear one, but here is the explanation:
Basically I want to call a member function to which I pass a lambda, and I want to access class members from the lambda like if the lambda itself was a class member.
I came up with this code which works as expected but which does not exactly what I want.
#include <iostream>
class MyClass
{
int member = 123;
public:
void SomeFunction()
{
std::cout << "SomeFunction()\n";
}
template<typename Functor>
void Test(Functor functor, int val)
{
functor();
std::cout << val << " " << member;
}
};
int main()
{
MyClass instance;
instance.Test([&instance] {std::cout << "Lambda\n"; instance.SomeFunction(); }, 42);
}
There are two things that bother me:
in the lambda I need to mention explicitly the captured class instance.
but more importantly: in the lambda there is no way to access private class members
I'd like to be able to write:
{std::cout << "Lambda\n"; instance.SomeFunction(); }
instead of:
{std::cout << "Lambda\n"; SomeFunction(); }
and even:
{std::cout << "Lambda\n"; instance.member; } // access private members from lambda
Is there some way to do this?
This works with GCC 10.3 using --std=c++20. Instead of capturing the instance when defining your lambda just pass it to the functor as a reference (this way you can reuse it). As for accessing private members just forget about it, it's not worth the time, and defeats the meaning of private. Just make the member public.
Passing the functor as a non-type template argument is optional (it could be a function argument, avoiding the need for C++20)
#include <iostream>
class MyClass
{
public:
int member = 123;
void SomeFunction()
{
std::cout << "SomeFunction()\n";
}
template<auto functor>
void Test(int val)
{
functor(*this);
std::cout << val << " " << member << std::endl;
}
};
int main()
{
MyClass instance;
auto lambda = [](auto& _instance) {std::cout << "Lambda\n"; _instance.SomeFunction(); };
instance.Test<lambda>(42);
}

Weird template and member function pointer error (C2373, C2530)

I came up with the following code when learning signal & slot, template, and function pointer.
Basically I am trying to make 2 classes, the base one will takes normal function pointers while the derived one will takes member function and wrap it up with a normal function, then pass it to the base class for invoking.
Here is the code:
#include<iostream>
struct foo {
void onNotify(int a, int b) {
std::cout << "member function: this=" << this << " a=" << a << " b=" << b << "\n";
}
};
void onNotify(void*, int a, int b) {
std::cout << "normal function: no context needed! a=" << a << " b=" << b << "\n";
}
// invoker that will takes normal functions.
template <typename...>
class invoker{
public:
invoker(void (*fptr)(void*, int, int), void* context){
fptr(context, 1, 2);
}
private:
invoker(){}
};
// invoker that will takes member functions.
template<class T>
class invoker<T> : public invoker<>{
public:
invoker<T>(T* context) : invoker<>(&forwarder, context){}
private:
invoker<T>(){}
static void forwarder(void* context, int i0, int i1) {
static_cast<T*>(context)->onNotify(i0, i1);
}
};
int main()
{
invoker<>(&onNotify, 0); // OK.
invoker<foo>(new foo); // OK.
invoker<foo>(0); // OK.
foo foo_;
auto f = invoker<foo>(&foo_); // OK.
// Errors:
// C2373 : 'foo_' : redefinition; different type modifiers.
// C2530 : 'foo_' : reference must be initialized.
invoker<foo>(&foo_); // ERROR!
return 0;
}
My questions are:
1) What is causing the compile error?
2) Why invoker<foo>(0); will actually run without error?
Thanks in advance!
1) The problem is that
invoker<foo>(&foo_);
is parsed as a definition of variable foo_ that has type invoker<foo>& rather than a call to the ctor of invoker<foo>. There is a number of ways to fix this, for example, use extra parentheses:
(invoker<foo>)(&foo_);
2) The code
invoker<foo>(0);
compiles without an error because it's unambiguous (it can't be interpreted as a declaration).

C++11 Lambda Template Infering

So I have the following code:
#include <iostream>
template <typename T>
class funcky
{
public:
funcky(char const* funcName, T func)
: name(funcName), myFunc(func)
{
}
//private:
char const* name;
T myFunc;
};
#if 0
int main(void)
{
char const* out = "nothing";
// requires template args
funcky test("hello", [&](int x, int y) -> int
{
out = "YES";
return x + y;
});
std::cout << test.name << " = " << test.myFunc(1, 2) << std::endl;
std::cout << test.name << " = " << out << std::endl;
return 0;
}
int main2(void)
{
funcky<void(*)(void)> test("hello", [&, this](void) -> void
{
std::cout << this->name << std::endl;
});
test.myFunc();
return 0;
}
#endif
int main(void)
{
char const* out = "nothing";
auto myFunc = [&](int x, int y) -> int
{
out = "YES";
return x + y;
};
funcky<decltype(myFunc)> test("hello", myFunc);
std::cout << test.name << " = " << test.myFunc(1, 2) << std::endl;
std::cout << test.name << " = " << out << std::endl;
return 0;
}
The top chunk is a function holder that holds a lambda and a name for it.
Next is what I'd like to use API-wise, but fails due to no template arguments being specified.
After that, there's my wondering if it's possible to have a 'this' of a specific type (such as funcky) be used in a lambda not declared inside it. Wishful thinking.
At the very end is code that compiles but uses a lambda outside the funcky constructor and decltype.
Are such things possible in C++11? How I accomplish said things?
Also unless it can kind of have the same API, try not to guess what I'm doing as if I can't do it this way, I'll just rewrite it in a simpler way. It's not worth the effort.
If you want to provide a way for a user to supply a callback to your class, you're better off using std::function, since templating the class on the function / functor type is not a very useful thing to do, as you experienced.
The problem arises from the fact that you can't just take anything in. You should have clear requirements on what can be passed as a callback, since you should know how you want to call it later on. See this on why I make the constructor a template.
#include <functional>
#include <utility>
struct X{
template<class F>
X(F&& f) : _callback(std::forward<F>(f)) {} // take anything and stuff it in the 'std::function'
private:
std::function<int(int,int)> _callback;
};
int main(){
X x([](int a, int b){ return a + b; });
}
If, however, you don't know how the callback is going to be called (say, the user passes the arguments later on), but you want to support that, template your type on the signature of the callback:
#include <iostream>
#include <functional>
#include <utility>
template<class Signature>
struct X{
template<class F>
X(F&& f) : _callback(std::forward<F>(f)) {} // take anything and stuff it in the 'std::function'
private:
std::function<Signature> _callback;
};
int main(){
X<int(int,int)> x1([](int a, int b){ return a + b; });
X<void()> x2([]{ std::cout << "wuzzah\n";});
}
Something like
template<typename Functor>
funcky<typename std::decay<Functor>::type>
make_funcky(const char* name, Functor&& functor)
{ return { name, std::forward<Functor>(functor) }; }
can be helpful for things like:
auto test = make_funcky("hello", [&](int x, int y) -> int
{
out = "YES";
return x + y;
});
However, inside a lambda expression this always refers to the immediate this outside of the expression. It's not a delayed reference to some this present at the time of the invocation -- it's not an implicit parameter. As such it doesn't make sense to want 'another type' for it.

C++: Class member functions as event callbacks

I'm trying to add a simple messaging system to my project, where events can be invoked by a function, which will lead to all callbacks registered to that event being called.
Now, the logical way to do this is using function pointers. It would be easily possible to pass the pointer to the desired callback function to the events manager, for registering. An event callback function would always return an int and take a void* as argument.
However I don't want to register static global functions as my event callbacks - I'd like to do it with class member functions.
Is it even possible to accomplish this with C++? Storing and calling pointers to member functions of different classes but with the same function header.
If this is not possible, do you have any suggestions on how I could work around this? I'd really like to add event listeners directly to my classes.
Yes it is possible. C++0x has the function class that handles this, and as others have pointed out Boost has similar facilities.
You can also roll your own, but the syntax is not for the faint of heart:
#include <iostream>
class Callable
{
public:
virtual ~Callable() {}
virtual int operator() (void* args) = 0;
};
class CallableFreeFunction : public Callable
{
public:
CallableFreeFunction(int (*func)(void*)) : func_(func) {}
virtual int operator() (void* args) { return (*func_)(args); }
private:
int (*func_)(void*);
};
template <typename tClass>
class ClassMemberCallable : public Callable
{
public:
ClassMemberCallable(tClass* instance, int (tClass::*memberfunction)(void*)) : instance_(instance), memberfunc_(memberfunction) {}
virtual int operator() (void* args) { return (instance_->*memberfunc_)(args); }
private:
tClass* instance_;
int (tClass::*memberfunc_)(void*);
};
class Foo
{
public:
int derp(void* args)
{
std::cout << args << '\n';
return 2;
}
};
int freefunctionfoo(void* args)
{
std::cout << "free" << args << '\n';
return 2;
}
int main(int argc, char* argv[])
{
Foo myfoo;
Callable* callable = new ClassMemberCallable<Foo>(&myfoo, &Foo::derp);
(*callable)(0);
delete callable;
callable = new CallableFreeFunction(freefunctionfoo);
(*callable)(0);
delete callable;
std::cin.get();
return 0;
}
This demonstrates a way of handling both free functions, and member functions in an opaque way. This is a simple example, and can be made more generic and robust in a number of ways. I'd refer you to these pages for syntax help:
http://www.newty.de/fpt/index.html
http://www.parashift.com/c++-faq-lite/pointers-to-members.html
I'd also recommend looking at this for more ideas:
http://www.codeproject.com/KB/cpp/FastDelegate.aspx
Of course it's possible ! Have a look at Boost.Signal2 and Boost.Bind.
Boost.Signal2 basically implements a signal and slots system which is exactly what you need.
Then, you can use boost::bind which is a generalization of std::bind1st and std::bind2nd to get function object wrappers to basically anything you can think of (in your case, member methods). It's really powerful.
See this official boost tutorial.
Here is my not-so-good attempt for doing a job like that:
First of all you need a base event handler class, well let's call it EvtHandler for now:
class Event; //implement this yourself, it shall contain general but good info about event
class EvtHandler
{
public:
virtual void handleEvent (Event & evt);
};
Then every class that is supposed to handle events in a way, should derive from this class, and they can implement new functions as much as they want as far as they return the same data type (void in this case) and recieve the same paramteres (Event in this case). Like this:
class Foo : public EvtHandler
{
public:
void handleFooEvent (Event & event);
};
Then I implemented message centers for each special event, which had to register listeners and dispatch events when needed:
class ShutdownMessageCenter
{
typedef std::map<EventHandler *, event_func> ListenerMap;
public:
void register (EvtHandler * handler, void(EvtHandler::*memFunc)(Event &)) {
m_lmap[handler] = memFunc;
}
void callListeners () {
Event shutdown_event (EM_SHUTDOWN /*just imagine this can mean something, idk*/);
ListenerMap::iterator itr = m_lmap.begin ();
for (; itr != m_lmap.end(); ++itr) {
EvtHandler * handler = itr->first;
void (EvtHandler::*func)(Event &) = itr->second;
(handler->*func)(shutdown_event);
}
}
private:
ListenerMap m_lmap;
};
Then you could register your EvtHandlers to this particular message center for example!
ShutdownMessageCenter message_center;
EvtHandler * some_handler = new EvtHandler ();
Foo * some_foo = new Foo ();
message_center.register (some_handler, &EvtHandler::handleEvent);
message_center.register (some_foo, static_cast<void (EvtHandler::*)(Event &)>(&Foo::handleFooEvent);
message_center.callListeners ();
But once again this is not good at all, just thought I would share! Sorry for the mess, haha!
I am not completely sure what you want to archive but maybe you should look at Boost Signals2
It is quite helpful if you want to create some sort of Signal/Slot mechanism.
No, it is not possible (unless you do c++/cli with .net).
Now, you can still create static functions, pass them an object as a parameter, and the only thing that they'll do is call your member function on that object. (Actually a cast will be required first).
The closest that I have managed is to register a static member function as the callback. The static member takes the object (this) pointer as an argument in addition to the arguments sent by the event handler and uses this to call the member function.
class myClass{
public:
static void callback(void *arg, void *obj)
{
if (obj)
reinterpret_cast<myClass*>(obj)->cb(arg);
}
private:
void cb(void *arg);
};
Register myClass::callback and this with your handler. You may need to wrap this in the structure that arg references if you are restricted in what can be returned.
I am using lukes answer with SWIG because SWIG does not support all C++11 features... This probably can be improved even further with Parsa Jamshidis approach.
I modified it to cover even more cases (variable amount of arguments and variable return type):
#include <iostream>
template <typename R, typename ...T>
class Callback
{
public:
virtual ~Callback() {}
virtual R operator() (T... args) = 0;
};
template <typename R, typename ...T>
class FreeCallback : public Callback<R, T...>
{
public:
FreeCallback(R(*func)(T...)) : func_(func) {}
virtual R operator() (T... args) { return (*func_)(args...); }
private:
R(*func_)(T...);
};
template <typename tClass, typename R, typename ...T>
class MemberCallback : public Callback<R, T...>
{
public:
MemberCallback(tClass* instance, R (tClass::*memberfunction)(T...)) : instance_(instance), memberfunc_(memberfunction) {}
virtual R operator() (T... args) { return (instance_->*memberfunc_)(args...); }
private:
tClass * instance_;
R (tClass::*memberfunc_)(T...);
};
class foo {
public:
Callback<int, int> *IntCallback;
Callback<int, int, double, double> *IntDoubleDoubleCallback;
};
class blub {
public:
int func1(int i) {
std::cout << "args: " << i << std::endl;
return 1;
}
int func2(int i, double d1, double d2){
std::cout << "args: " << i << " " << d1 << " " << d2 << std::endl;
return 0;
}
};
int freeFunc1(int i) {
std::cout << "args: " << i << std::endl;
return 1;
}
int freeFunc2(int i, double d1, double d2){
std::cout << "args: " << i << " " << d1 << " " << d2 << std::endl;
return 0;
}
int main() {
foo f;
blub b;
f.IntCallback = new MemberCallback<blub, int, int>(&b, &blub::func1);
f.IntDoubleDoubleCallback = new MemberCallback<blub, int, int, double, double>(&b, &blub::func2);
Callback<int, int> *IntFreeCallback = new FreeCallback<int, int>(&freeFunc1);
Callback<int, int, double, double> *IntDoubleDoubleFreeCallback = new FreeCallback<int, int, double, double>(&freeFunc2);
int ret = (*IntFreeCallback)(42);
std::cout << "ret freeFunc1: " << ret << std::endl;
ret = (*IntDoubleDoubleFreeCallback)(42, 3.1415, 2.7182);
std::cout << "ret freeFunc2: " << ret << std::endl;
ret = (*f.IntCallback)(42);
std::cout << "ret func1: " << ret << std::endl;
ret = (*f.IntDoubleDoubleCallback)(42, 3.1415, 2.7182);
std::cout << "ret func2: " << ret << std::endl;
std::cout << "Hello World!\n";
// cleanup not done here...
}