hello and thanks in advance for supporting,
I'm trying to send a pointer to function which is type void and receive nothing.
it didn't work well so far.
here is my minimal code that have this problem:
void func::foo()
{
return;
}
and the function which use it is:
void func::create_func(void(*wanted_func)())
{
wanted_func();
}
the problem is when it called:
create_func(foo);
please advice,
I hope i haven't asked something that is very silly
From what I understand, you'd like to pass a member method pointer to another member method. So you'll have to bind an object instance to the method that you want to pass.
Have a look at std::bind (Reference)
Here is a minimal example which I believe does what you want:
#include <iostream>
#include <functional>
class Func {
public:
void foo() {
std::cout << "called foo\n";
}
void create_func(std::function<void()> functor) {
functor();
}
};
int main() {
Func f;
f.create_func(std::bind(&Func::foo, f));
return 0;
}
[New to CPP bind] I understand bind_front when it is used on context of non class functions. Can someone help me understand the following piece of code, which uses bind_front in context of class ?
#include <iostream>
#include <functional>
class foo
{
void bar() { std::cout << "foo::bar" << '\n'; }
};
int main()
{
Foo my_foo;
auto f1 = std::bind_front(&foo::bar, &my_foo);
f1();
}
Essentially whats binding a function to a class pointer does ?
As documented, calling the function-call operator of the object returned bystd::bind_front function is equivalent to calling std::invoke.
And std::invoke is specified to take the first function argument (i.e. &my_foo in your example) and use as the object to call the member function on.
So your call
f1();
is equivalent to
std::invoke(&foo::bar, &my_foo);
which is equivalent to
(&my_foo)->bar();
So, I was trying to get this working:
#include <iostream>
#include <functional>
using namespace std;
class X {
public:
template<typename T>
void f(T t) {
cout << t << endl;
}
};
int main() {
X xx;
xx.f(5);
function<void(int)> ff(&X::f);
return 0;
}
Compiler complains that X::f is <unresolved overloaded function type>, which makes sense. Now, my questions is: how do I tell the compiler which template parameters to use? I essentially want something like
&X::template<int> f
(the equivalent of dot-template for object methods). Any help would be much appreciated.
You would need:
function<void(X, int)> ff(&X::f<int>)
ff(xx, 5);
because you asked for a non-static member function meaning you need to provide the instance on which the function is invoked to std::function. For example: http://ideone.com/dYadxQ
If your member f doesn't actually need an X to operate, you should make it a "free" nonmember function rather than a member function of X.
typedef boost::function<void (int,bool)> MyCallback;
void RegisterCallback(MyCallback callback);
class A {
public:
void GoodCallback(int intArg,bool boolArg) {
printf("calling GoodCallback (%d,%s)\n",intArg,boolArg?"true":"false");
}
void BadCallback(int intArg) {
printf("calling BadCallback (%d)\n",intArg);
}
};
int TestFunction() {
A * myA=new A();
RegisterCallback(boost::bind(&A::GoodCallback,myA,_1,_2));
RegisterCallback(boost::bind(&A::BadCallback,myA,_1));
return 0;
}
Is there any way that I can make the second call to RegisterCallback not compile?
For context:
I recently changed the callback signature and added the bool argument. I thought I had updated everything that was using this, but I was mistaken. Other than renaming RegisterCallback everytime I change the signature, I would like to have a way to have the compiler enforce that all arguments are used.
The documentation says
Any extra arguments are silently ignored
It has to be this way in order to support _N placeholders. Witness:
void foo (int a, const char* b) {
std::cout << "called foo(" << a << "," << b << ")" << std::endl;
}
int main () {
boost::bind(foo,_1, _2)(1, "abc", foo, main, 2.0);
boost::bind(foo,_2, _5)(3.0, 2, foo, main, "def");
}
prints
called foo(1,abc)
called foo(2,def)
Any combination of arguments in the beginning, in the end or in the middle of the argument list can be ignored.
You need a simpler binder that doesn't support anything like _N placeholders. Boost doesn't seem to have one.
The problem isn't boost::function; the problem is that the function object boost::bind returns will take anything as parameters. Bind is, more or less, runtime defined, not compile-time defined. Therefore, the boost::bind object can be used with any boost::function.
[edit] OK, apparently boost::function is also a problem. But it's not the only problem.
You could always use std::function<...> instead.
The following does not compile on VS2010 SP1:
#include <functional>
void foo();
void bar(int);
int main()
{
std::function<void ()> f= std::bind(foo);
std::function<void ()> g= std::bind(bar); // does not match signature, does not compile.
return 0;
}
I'm a bit late with this answer but since the problem is the binding you could do this step later with the help of a templated version for your callback registration function and another one for regular function pointers:
template<typename C>
void RegisterCallback(void (C::* func)(int, bool), C* inst)
{
MyCallback callback(boost::bind(func, inst, _1,_2));
}
void RegisterCallback(void (*func)(int, bool))
{
MyCallback callback(func);
}
A * myA = new A();
RegisterCallback(&A::GoodCallback, myA);
RegisterCallback(&A::BadCallback, myA); // DOES NOT COMPILE
RegisterCallback(GoodCallback);
RegisterCallback(BadCallback); // DOES NOT COMPILE
This works as expected in VS2010 but has the disavantage of needing not one but two callback registration functions to correctly deal with member and non-member functions.
As another option you might have a look at the boost function_types library. It provides a parameter_types metafunction that extracts the parameter types of function pointers and returns them as a MPL sequence. Then with a bit template magic it's possible to validate the parameters of the callback function, something like:
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/mpl/equal.hpp>
using namespace boost;
using namespace boost::function_types;
template< typename Function >
void RegisterCallback(Function f)
{
BOOST_MPL_ASSERT((
mpl::equal<
parameter_types< Function >,
parameter_types< void(int,bool) >
>
));
MyCallback callback(f);
}
template<typename Function, typename T>
void RegisterCallback(Function f, T* inst)
{
BOOST_MPL_ASSERT((
mpl::equal<
parameter_types< Function >,
parameter_types< void (T::*)(int,bool) >
>
));
MyCallback callback(boost::bind(f, inst, _1, _2));
}
This also works as expected in VS2010 but you still need two function declarations although it should be possible to pack them in one if you define them inside a struct (and use a default template parameter argument for T);
#include "stdafx.h"
#include <iostream>
using namespace std;
template<class Type>
struct X
{
void run()const
{//Why on earth this doesn't work?
[&]()
{
Type::alloc();
};
}
void run_1()const
{//if this does
Type::alloc();
}
};
struct T
{
static void alloc()
{}
};
int _tmain(int argc, _TCHAR* argv[])
{
X<T> x;
x.run_1();
return 0;
}
AFAIC lambda is a unnamed fnc, so if that's true why run doesn't compile and run_1 does?
Using VS2010 sp beta1.
You'll have to pass it in to the lambda:
void run()const
{//Why on earth this doesn't work?
auto alloc = Type::alloc;
[&]()
{
alloc();
};
}
I have to admit I am not quite sure, but I think is only a VS 2010 limitation and it should compile fine in C++0x (cf. templates, typename, lambda -> dependent names not dependent?). I think the mechanics of what you see are like following:
When defining template, types defined by template parameters are not "fully fledged" typenames in some aspects. One example demonstrating this is that while someone might expect X<Foo>::Type (with X from your example) to return Foo, it does not.
You have to call the lambda. It is a functor so you need a () at the end of it to effectively call the lambda.
/* Code does NOT answer question above...
void run()const
{//Why on earth this doesn't work?
[&]()
{
Type::alloc();
}(); //very important parenthesis if you wish to call the lambda
}*/
I seem to have misread the question. Sorry.
But there is already a similar post on SO Template type is not "seen" by the compiler inside a lambda
And here is another link that refers to the same problem, with a quote from the standard about this.
templates, typename, lambda -> dependent names not dependent?