I'm having some trouble creating a static wrapper function using template parameters. I don't want to pass the function directly to the wrapper function, because it needs a specific signature int (lua_State *) so that it can be passed into the following function:
lua_pushcfunction(L, function);
(That's right, I'm going for an auto-generated lua wrapper.)
My first thought is to create a template function with a function pointer as a non-type template argument.
template <void(* f)(void)>
int luaCaller(lua_State * _luaState)
{
f();
return 0;
}
So far, this is looking pretty good. This function has the proper signature, and calls a function I pass in via template argument.
&(luaCaller<myFunc>)
My problem arises when I try to wrap this in another function. Non-type template parameters must be externally linked, and thus the following fails:
void pushFunction(lua_State * _luaState, void(* _f)(void))
{
lua_pushcfunction(_luaState, &(luaCaller<_f>));
}
Which makes sense, because the address of the function needs to be known at compile time. You can't throw in just any pointer and expect the compiler to know which classes to create. Unfortunately, if I add a function pointer that is known at compile time it still fails. The value of the function pointer is being copied into _a, and therefore _a is still technically not known at compile time. Because of this, I would expect the following to work:
void pushFunction(lua_State * _luaState, void(* const _f)(void))
{
lua_pushcfunction(_luaState, &(luaCaller<_f>));
}
or maybe
void pushFunction(lua_State * _luaState, void(* & _f)(void))
{
lua_pushcfunction(_luaState, &(luaCaller<_f>));
}
In the first case, because the value isn't allowed to change, we know that if it is externally linked, it will still technically be externally linked. In the second case it's being passed in as a reference, which would mean it should have the same linkage, no? But neither of these attempts work. Why? Is it possible to circumvent this somehow? How can I cleanly auto generate a function that calls another function?
The const qualifier means you aren't allowed to change something, not that it's a compile-time constant. The initial value of _a is determined at runtime when the function is called, and for a * const &a, the value can even change at runtime by some external means such as another thread, if the object underlying the reference is not const.
To make the fully templated wrapper work, you need to give the compiler enough information to compile a function for each possible template argument, and provide logic to switch among those functions. The template system generates and organizes related functions, but it's not a dynamic dispatcher.
If you can add the function pointer to the lua_State object and eliminate the template parameter, that would be one solution.
Your solution would work if make the function pointer a template argument to doCaller, but that would defeat its purpose.
Rather than using a non-type function-template approach in order to bind the secondary function you want to call inside the wrapper-function, you could use a struct with a static luaCaller method. That should allow you to maintain the function signature you need for passing luaCaller to lua_pushcfunction.
So for instance, you could have a struct that looks something like the following:
template<void (*f) void>
struct wrapper
{
static int luaCaller(lua_State * _luaState)
{
f();
return 0;
}
};
template<typename Functor>
void doCaller(lua_State * _luaState, Functor wrapper)
{
Functor::luaCaller(_luaState);
}
then call it like:
doCaller(&luaState, wrapper<my_func>());
Related
I'm trying to write a wrapper for a "register callback" type of interface from a C library. The issue is quite complicated by the fact that, the library lets you register "variadic" functions by accepting a list of parameter definitions. Then at callback time, the function is expected to extract its arguments from a type-erased list of arguments. Good old C...
The interface I'm trying to create is to accept any function, even a lambda, and automatically generate all the machinery to correctly register this function, along with registering the arguments and extracting them during callback time. So the user should only have to type:
register_callback("Callback Name", [](int i){return i+0.5;});
Now this is theoretically possible, but at one point, I need to be able to call the lambda without any instance, but with access to only its type. I don't understand why, but the default constructor of a stateless (non-capturing) lambda is deleted, so I can't simply default-construct from its type. What I'm planning to do instead is a very dirty-looking, but should probably be OK way to work around this:
template <class Func, class RET, class ...ARGS>
struct from_stateless {
static RET to_function(ARGS...args) {
RET (*f)(ARGS...) = *(Func *)(0);
return f(args...);
}
};
so that from_stateless<LAMBDA_TYPE, RET, ARGS...>::to_function is actually a function pointer that I can call without an argument and more importantly one that I can pass as a TEMPLATE ARGUMENT.
Under normal circumstances, the line RET (*f)(ARGS...) = *(Func *)(0); would be suicide, but it really should be safe with this use case, isn't it? After all, the function pointer obtained after conversion couldn't in any universe possibly depend on the lambda instance.
So, the question is, is it safe to do this as long as I make sure that the type is indeed a stateless lambda? Or am I missing something? Note that the RET (*f)(ARGS...) = *(Func *)(0); would trigger a compiler error if a closure accidentally slips through.
CLARIFICATION: I can't just decay the lambda to a function pointer and register it, since the signature of the lambda is not compatible with the "Register" method. The register method expects a function with signature: void (*)(int number_of_args, TypeErasedValue * arguments, TypeErasedValue * result) So you see, I need to (and already do), through template metaprograming, generate a free function templated on the type of the lambda to act as an adaptor between the expected and the actual signatures.
It gets even easier than #Yakk's answer if you take advantage of the fact that a lambda can see the static locals of its enclosing scope without needing to capture them. Using this fact you can wrap the user-provided stateless lambda in your own stateless lambda with the required signature, and convert the latter into a function pointer.
using callback = void (*)(int, TypeErasedValue*, TypeErasedValue*);
template <typename F>
callback stateless_to_callback(F f) {
static F static_f = f;
return [](int argc, TypeErasedValue* argv, TypeErasedValue* result) {
// extract arguments from argv
auto r = static_f( /* arguments... */ );
// store r in result
};
}
Want defined behaviour?
Add:
static Func state(Func* op=0){
static Func f=*op;
return f;
}
to your template class. First time you call it, pass a ptr to lambda. 2nd time, extract value for free.
The static Func f is constructed the first time the function is called: so long as the pointer is non-null that time, we are good. Every other time it is called, the pointer can be null and it does not use it, as static locals are only constructed once.
Call it to 'register' with pointer to lambda. Elsewhere (at callback), call it to get a copy. Lambda is stateless, so copy is free.
Assuming you have something to register normal function
template <typename Ret, typename... Args>
void register_callback(const std::string& s, Ret(*)(Args...))
{
std::cout << "register function " << s << std::endl;
// Implementation
}
You may simply explicitly convert your non-capturing lambda in pointer on function:
template <typename Lambda>
void register_callback(const std::string& s, const Lambda&f)
{
// convert non capturing lambda into function pointer
Register(s, +f);
}
Live demo
or change your call site to something like:
register_callback("Callback Name", +[](int i){return i + 0.5;});
Note: You may use * instead of + for the decay.
I don't understand why the following code compile and works:
template<typename Predicate>
void foo(Predicate p) {
}
bool g(int n) {
}
void user(int n) {
foo(g);
}
foo is supposed to get a function object that will run on a data structure but I made the method simpler, because what I don't understand is how can this works? A method isn't an object. The normal way to do it is to create a new class, override operator() and then send an instance of that class.
Well, in this case the Predicate parameter is substituted by a function pointer of type bool (*func) (int). Nothing wrong with that...
The Predicate template argument can be almost any type. So you can use it for function pointers and classes as well as the basic types.
If you use the function argument p as a function, then it can be anything that is callable, like a function pointer, an object whose class have an operator() member function, a pointer to a static member function, a std::bind object, a std::function object or a lambda expression.
It can't be a pointer to a member function though, because to call a pointer to a member function you need an instance to call it on. For this use std::bind.
I'm developing a templated binary search tree in C++ for a data structures class right now. Everything has been going well until now. This issue deals with some nitty gritty C++ stuff that I'm not to familiar with, and I need help.
I've previously defined functions that traverse the tree and visit each node in different orders. The one in question here is defined as follows.
TreeNode.h
public:
static void PostOrderVisit(TreeNode<T>* node, void visit(const T& v));
TreeNode.cpp
template <class T> void TreeNode<T>::PostOrderVisit(TreeNode* node, void visit(const T& v)) {
if (node->leftChild != NULL)
PostOrderVisit(node->leftChild, visit);
if (node->rightChild != NULL)
PostOrderVisit(node->rightChild, visit);
visit(node->value);
}
This works fine in a test program that makes nodes and statically calls PostOrderVisit.
In a friend class (BinSTree.h/cpp), I am implementing a method that deletes every node in the tree, so I thought it would be a good idea to use this visitor and call my Delete() function on each node (the Delete() function also works fine in test programs for the BinSTree).
This function is defined as follows.
template <class T> void BinSTree<T>::ClearTree() {
TreeNode<T>::PostOrderVisit(this->root(), &BinSTree<T>::Delete);
}
And here lies the problem. g++ says...
BinSTree.cpp:156: error: no matching function for call to ‘TreeNode<int>::PostOrderVisit(TreeNode<int>*, void (BinSTree<int>::*)(const int&))’
TreeNode.cpp:56: note: candidates are: static void TreeNode<T>::PostOrderVisit(TreeNode<T>*, void (*)(const T&)) [with T = int]
In this case, I thought that void (BinSTree<T>::*)(const T&) would be an instance of void (*)(const T&), but it is not. The only way I can get the call to be recognized by the function definition is by casting the function pointer like this:
TreeNode<T>::PostOrderVisit(this->root(), (void (*)(const T& v)) &BinSTree<T>::Delete);
This recognizes the function and calls it appropriately, however (this took some significant research...), C++ member functions have an implicit parameter that allows the 'this' keyword to be accessed from within. Casting a member function pointer to a plain function pointer drops the 'this' reference altogether, causing my Delete() method to seg fault (it uses 'this' quite a bit).
This has been a HELL of a hassle, and I have spent quite a bit of time on such a small bit of this project. Can anyone show me a way to either A: make the function be recognized without the casting, or B: how to maintain the 'this' reference throughout the cast. The ClearTree() and Delete() methods are both within the same class.
Thanks in advance.
First of all, PostOrderVisit should take the function argument as a pointer, i.e. PostOrderVisit(TreeNode<T>* node, void (*visit)(const T& v)).
However, that wont solve your problem because you are passing it a non-static member function. Either the function you pass to it has to be static in the class, or you can use something like std::function instead of a function pointer argument, i.e. PostOrderVisit(TreeNode<T>* node, std::function<void(const T&)> visit).
Edit
In that case I think you have two ways you can do this: One is to change your design to fit the parameter, that means you can not use member methods as a parameter. The second is to change the code to fit your design, and explain to the teacher that you had to change the interface due to its limitations, and explain those limitations.
The problem with using a normal function pointer as argument is that member functions have an implicit and hidden argument, this, for the instance of the class. Normal functions do not have this hidden parameter, and so the compiler prohibits you from using a member function. The solution is to either use normal functions, which is not very C++-ish, another is to use static member functions (as they don't have a this pointer), or use something like std::function.
As for how to use std::function, you use it in the declaration and definition of PostOrderVisit like I've shown. When you call it you do something like this:
template <class T> void BinSTree<T>::ClearTree() {
TreeNode<T>::PostOrderVisit(this->root(), std::mem_fn(&BinSTree<T>::Delete));
}
Non-static methods take an implicit parameter for "this". E.g. for a method C::f(int i), you can think of it like f(C* this, int i). Any casting that you do and screws up this signature you can expect badness to happen. You have already experienced crashes but more sinister artifacts could make the program misbehave or crash at other seemingly random places.
You can use pointer to member function like this:
in .h
template <class C>
static void PostOrderVisit(C* node, void (C::* visit)(const T& v));
in .cpp (actually if it is a template it has all to be in h, otherwise link error)
template <class T>
template <class C>
void TreeNode<T>::PostOrderVisit(C* node, void (C::* visit)(const T& v))
{
// ...
T value;
(node->*visit)(value);
// ...
}
You either pass pointer to your derived class (C as in here) or pointer to base class (TreeNode as in original). At some point you may need to cast.
You can also leave original function for when you pass a normal function as visitor. Function overload would take care.
A more generic way can be to use std::function. Although it may have some minor performance hit it would be most generic.
e.g. (have not compiled may have some minor syntax errors):
static void PostOrderVisit(TreeNode<T>* node, std::function<void (const T& v)> visit);
Inside PostOrderVisit you just do visit(value), e.g. call like normal function.
When you call PostOrderVisit you can use all the power of std::bind or boost::bind to carry as much extra info as you wish. E.g.
PostOrderVisit(this->root(), std::bind(&BinSTree::Delete, this));
I have a class X which has this method:
void setRxHandler(void (*h)(int));
And I want to pass to it a member function that exists in instances of class Y.
void comm_rxHandler(int status);
I tried the following:
x.setRxHandler(comm_rxHandler)
But it get the following compile error (I'm using Qt):
error: no matching function for call to
‘X::setRxHandler(< unresolved overloaded function type>)’
So, how can I do that?
I noticed if I declare comm_rxHandler (class Y) as static, I have no errors. But I want comm_rxHandler as a non-static method. Also I want setRxHandler method (class X) to be generic and not class-specific. So I can't declare that method as:
setRxHandler(void (Y::*h)(int))
How to do that? Can you help me on this?
Thanks!
C++ doesn't support bound methods. To invoke a member function through a function pointer, you need to have two things: an instance of the class and the function pointer.
So setRxHandler(void (Y::*h)(int)) is almost correct. You need to declare it as:
void setRxHandler(Y*, void (Y::*h)(int));
To invoke setRxHandler(), you need to pass it arguments as follows:
Y y;
setRxHandler(&y, &Y::comm_rxHandler);
In the setRxHandler() method, you can invoke the function pointer using this syntax:
void setRxHandler ( Y* y, void (Y::*h)(int) )
{
// ...
(y->*h)(0);
// ...
}
To make generic, you need to abstract the Y parameter away, but this is difficult to get right. Check out Boost.Function for an existing implementation that supports this use case, and many more.
Change your callback to this:
void setRxHandler(std::function(<void(int)>);
Then you can use binders:
setRxHandler( std::bind(&class_name::comm_rxHandler, obj) );
(std::function and std::bind are part of the upcomming next version of the C++ standard. It's quite likely your compiler already comes with them. If not, they might live in namespace std::tr1. If all else fails, you will find them at boost - which is where they were invented - as boost::function and boost::bind.)
You can, however, also pass non-member or static functions to setRxHandler, as well as function objects (which is the result of std::bind).
If your compiler already supports lambda functions (also part of the next standard, but already supported by, e.g., recent versions of GCC and VC), you can also use one of those:
setRxHandler( [](){obj.comm_rxHandler();} );
As it is now, the setRxHandler prototype takes a pointer to a function that doesn't return anything and takes an int. As you have noticed, this won't work with member functions because they can't be called like a normal function (you have to handle the this pointer as well, which means having an instance of that class to call the method on).
To make it both work with member functions and non-specific (generic), you have to either make a base class and have all classes you want to use setRxHandler with derive from that class:
class Base { ... };
class Derived : public Base { ... };
// then for the prototype
void setRxHandler(void (Base::*h)(int)) { ... }
// and you can use setRxHandler for all types that derive from Base, which gives you more control than the second option, which is:
or use templates:
template<typename T>
void setRxHandler(void (T::*h)(int)) { ... }
With the template option, you really have no control over what class will be used with setRxHandler (excluding RTTI), which can be exactly what you want.
You can either make a base class for Y and use that (to avoid being "class specific"), or use templates:
template <class T>
setRxHandler(void (T::*h)(int));
But then this may raise questions of how to use the member function (you tell us if it does).
As others have already mentioned, C++ does not provide this functionality.
Another option you could use is libsigc++ which is widely used in gtkmm, see this example in their tutorial for instance on how to pass pointers to member-functions. Your example could look something like:
// sigc::slot<void, int> is a 'slot' to hold a function with return type void
// and 1 int argument.
void setRxHandler(sigc::slot<void, int> slot);
void comm_rxHandler(int status);
//sigc::mem_fun() can convert a member function to a function slot.
x.setRxHandler(sigc::mem_fun(*this, &X::comm_rxHandler));
i have made a sample example, in this i'm trying to pass a function as argument i am getting error, could you please help me
typedef void (*callbackptr)(int,int);
class Myfirst
{
public:
Myfirst();
~Myfirst();
void add(int i,callbackptr ptr)
{
ptr(i,3);
}
};
class Mysec
{
public:
Myfirst first_ptr;
Mysec();
~Mysec();
void TestCallback()
{
callbackptr pass_ptr = NULL;
pass_ptr = &Mysec::Testing;
first_ptr.add(2,&Mysec::Testing);
}
void Testing(int a,int b)
{
int c = a+b;
}
};
The type of the callback function you're passing as parameter is not defined as part of a class. You probably should define Testing as static.
You are geting an error because you are pointing to a member function. Pointers to member functions are different. See here:
http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.1
A member function needs to know what instance it is working with (the this pointer) so it can't be called like any other function. If you moved the callback function out of the class (or made it static, which is similar to moving it out of the class) you could call it like any other function.
A more modern way of doing this is to use functors, e.g. boost::function and something like boost::bind :
C++ Functors - and their uses
how boost::function and boost::bind work
Those can hide the difference between member and global functions.
You are trying to access a member function pointer here, using a simple function pointer typedef, which will not work. Let me explain.
When you write a normal, non-member function (similar to C), the function's code actually exists in a location indicated by the name of the function - which you would pass to a function pointer parameter.
However, in the case of a member function, all you have is the class definition; you don't have the actual instance of the class allocated in memory yet. In such a function, since the this pointer is not yet defined, any reference to member variables wouldn't make sense, since the compiler doesn't have enough information to resolve their memory locations. In fact, member function pointers are not exact addresses; they encode more information than that (which may not be visible to you). For more, read Pointers to Member Functions.