C++11 std::function: Binding a method without a particular instance - c++

Continuing this thread I'd like to split it off into another more specific question. I want to bind a function using ChaiScript, and I can do that using std::function, but I can't seem to let std::function know which overload it should use.
Mirroring relevant methods:
class DLLExport Actor
{
public:
Actor(Level* level, const String& name, Actor* parent);
virtual ~Actor();
void setPosition(const Real& x, const Real& y, const Real& z);
void setPosition(const Vector3& position);
};
and then I'm trying to bind it like so:
std::function<void(Actor*, Vector3&)> setPos = &Actor::setPosition; // <-- C2440 here.
m->add(fun(setPos), "setPosition");
What I'm getting is the following error:
2>..\..\ScriptingDemo\Binder.cpp(63): error C2440: 'initializing' : cannot convert from 'overloaded-function' to 'std::function<void (Actor *, Vector3 &)>'
2> No constructor could take the source type, or constructor overload resolution was ambiguous

Use a typedef to your member function :
typedef void (Actor::*set_type)(const Vector3&); // Note the syntax for a member function typedef
And use it for a clean static_cast to resolve the overload :
std::function<void(Actor&, const Vector3&)> setPos = static_cast<Actor::set_type>(&Actor::setPosition);
( note the implicit Actor& parameter to the member function, explicit in the above std::function<> signature)

C++ overloaded method pointer.
Basically, put in the cast manually.
std::function<void(Actor*, const Vector3&)> setPos((void(Actor::*)(const Vector3&))&Actor::setPosition);
Now the why:
The = operator for std::function is (itself) a template and provides no type information for its argument. So when you try to assign it to &Actor::setPosition, there is no good way for the compiler to figure out which function you are asking for. Putting in the cast fixes that.
The Actor* argument comes from the type of function Actor::* rather than the function signature itself.

You're trying to convert a member function pointer to a free function pointer, and that can't work. Were that possible, you forgot the const in the std::function template arguments anyway.
Your inclusion of an Actor* is on the right track though :
#include <iostream>
#include <functional>
struct Foo {
void bar(int const &i) { std::cout << i; }
};
int main()
{
using namespace std::placeholders;
std::function<void(Foo*, int const&)> func = std::bind(&Foo::bar, _1, _2);
Foo foo;
func(&foo, 17);
return 0;
}
Note that you still need to provide an instance to call the method on at one point, but what would you expect ?

Related

How to understand the typedef in this declaration

Recently, I read the book Effective C++ and there is a declaration about typedef in Item 35 which confuses me.
class GameCharacter; // Question1: Why use forward declaration?
int defaultHealthCalc(const GameCharacter& gc);
class GameCharacter{
public:
typedef int (*HealthCalcFunc)(const GameCharacter&); // Question 2: What does this mean?
explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc)
: healthFunc(hcf)
{}
int healthValue() const
{return healthFunc(*this); }
private:
HealthCalcFunc healthFunc;
};
So my first question is: Why does the author use a forward declaration here? Is there any specific reason?
And my second question is: How do I understand the typedef declaration, and how do I use it? I just know something like typedef int MyInt;
So my first question is that why the author use forward declaration here?
Because the declaration of the function defaultHealthCalc uses const GameCharacter& as the type of the parameter, then GameCharacter needs to be declared in advance.
And my second question is how to understand the typedef declaration
It declares a type name HealthCalcFunc, which is a type of pointer to function, which takes const GameCharacter& as parameter and returns int.
and how to use it?
Just as the code sample showed,
explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc) // declare a parameter with type HealthCalcFunc;
// the default argument is function pointer to defaultHealthCalc
: healthFunc(hcf) // initialize healthFunc with hcf
{}
int healthValue() const
{return healthFunc(*this); } // invoke the function pointed by healthFunc
HealthCalcFunc healthFunc; // declare a member with type HealthCalcFunc
The forward declaration is needed because of the forward declaration of defaultHealthCalc, which uses GameCharacter. Without forward declaration, the compiler would not know that later, there will be a type named GameCharacter, and so you need to forward declare it, or move the definition before the function declaration.
That typedef means to name the type int(*)(const GameCharacter&) HealthCalcFunc. That's a function pointer to a int(const GameCharacter&). For that reason, typedefs are pretty unreadable, it is advised to use a using declaration instead:
using HealthCalcFunc = int(*)(const GameCharacter&);
So my first question is that why the author use forward declaration here?
So that the compiler knows that GameCharacter is a valid name when the int defaultHealthCalc(const GameCharacter& gc); line is encountered.
And my second question is how to understand the typedef declaration and how to use it?
Ideally, you do not use it anymore.
Starting with C++11, using is a superior alternative because it's more readable; unlike typedef'ed function pointers, it clearly separates the name from that which the name describes. Compare this:
typedef int (*HealthCalcFunc)(const GameCharacter&);
With this:
using HealthCalcFunc = int (*)(const GameCharacter&);
In the typedef version, the name HealthCalcFunc is surrounded on both sides by that which the name describes. This hurts readability.
But the code can still be improved, because C++11 also introduced std::function as an alternative to and/or an abstraction layer above function pointers.
using HealthCalcFunc = std::function<int(const GameCharacter&)>;
This is so readable it hardly has to be explained at all. HealthCalcFunc is a function which returns an int and takes a const GameCharacter&.
The defaultHealthCalc function fits into this definition. Here's a full example:
#include <functional>
class GameCharacter;
int defaultHealthCalc(const GameCharacter& gc);
class GameCharacter {
public:
using HealthCalcFunc = std::function<int(const GameCharacter&)>;
explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc)
: healthFunc(hcf)
{}
int healthValue() const
{return healthFunc(*this); }
private:
HealthCalcFunc healthFunc;
};
The great thing about std::function is that you are not restricted to free-standing functions. You can pass every function-like thing. Here are some examples:
struct Functor
{
int f(const GameCharacter& gc);
};
int main()
{
// normal function:
GameCharacter character1(defaultHealthCalc);
// lambda:
GameCharacter character2([](auto const& gc) { return 123; });
// using std::bind:
Functor functor;
using namespace std::placeholders;
GameCharacter character3(std::bind(&Functor::f, functor, _1));
}
See also Should I use std::function or a function pointer in C++?.
typedef int (*HealthCalcFunc)(const GameCharacter&);
Declares a typedef named HealthCalcFunc for a function pointer type, where the function signature returns a int and takes a parameter of const GameCharacter&.
The forward declaration is needed because that class is used as parameter type in the typedef.
The forward declaration of GameCharacter is not strictly needed; the function declaration could have read:
int defaultHealthCalc(const class GameCharacter& gc);
which has the same effect as the original code. But it is considered more readable to have the forward declaration on its own line.

How to use a function of own class in for_each method?

Assume I have this class (inherited from std::Vector, it's just an example)
#include <vector>
using namespace std;
template <class T>
class C : public vector<T> {
// I don't want to use static keyword
void transformation(T i) {
i *= 100;
}
public:
void method() {
for_each(this->begin(), this->end(), transformation);
}
};
int main() {
C<double> c;
for (int i=-3; i<4; ++i) {
c.push_back(i);
}
c.method();
}
How do I call for_each using class method inside class itself? I know I can use static keyword, but what is there any other way how to use a function object without using static?
I get this error message while compiling:
for_each.cc:21:55: error: cannot convert
‘C::transformation’ from type ‘void (C::)(double)’
to type ‘void (C::*)(double)’ for_each(this->begin(),
this->end(), transformation);
I think I need to add .* or ->* somewhere but I can't find out where and why.
C++11 bind solution:
std::for_each(this->begin(), this->end(),
std::bind(&C::transformation, this, std::placeholders::_1));
C++11 lambda solution:
std::for_each(this->begin(), this->end(),
[this] (T& i) { transformation(i); });
C++14 generic lambda solution:
std::for_each(this->begin(), this->end(),
[this] (auto&& i) { transformation(std::forward<decltype(i)>(i)); });
C++98 bind1st+mem_fun solution:
std::for_each(this->begin(), this->end(),
std::bind1st(std::mem_fun(&C::transformation), this));
Note: this->begin() and this->end() calls are qualified with this-> only because in the OP's code they are member functions of a templated base class. As such, those names are primirarily searched in a global namespace. Any other occurrence of this is mandatory.
For starters, don't inherit from the standard containers, they are not designed to be inherited (no virtual destructors etc.).
Secondly, and regarding your problem, it's because a pointer to a member function is not the same as a pointer to a function. The reason is that member function has a hidden first parameter which becomes the this pointer in the function. The simplest way to solve it is to make the function static.
Another solution is to use the std::bind function that came with C++11:
for_each(this->begin(), this->end(),
std::bind(&C::transformation, this, std::placeholders::_1));
If you don't have C++11 (even though you tagged your question as such), then you probably could get something working with std::mem_fun or std::bind1st.
You need to bind the this pointer:
public:
void method()
{
for_each(this->begin(), this->end(), bind(&C::transformation, this, placeholders::_1));
}

compilation error: overloading operator()

VisualStudio 2008 (VC++ 9)
Problem with overloading operator()
Hello community!
It seems that overloaded version of operator() must all differ in their argument list, independly of the return type.
I have the following case:
class Sha256{
public:
QVector<quint32> operator()(QString const& data);
QByteArray operator()(QByteArray const& data);
QVector<quint32> operator()(QByteArray const& data); // this is line 168
...
}
Last declaration leads to following compilation error:
.\sha256.cpp(168) : error C2556: 'QVector Sha256::operator ()(const QByteArray &)' : overloaded function differs only by return type from 'QByteArray Sha256::operator ()(const QByteArray &)'
with
[
T=uint
]
On the other side, following declarations are working:
class Sha256{
public:
QVector<quint32> operator()(QString const& data);
QByteArray operator()(QByteArray const& data);
...
}
because they have different arguments.
One way would be to add in the first case an additional argument like
QByteArray<quint32> operator()(QByteArray const& data, bool getByteArray)
but this is embarassing, not intuitive and also not clean (return type would be a QByteArray, independly of the value of getByteArray, even in case of false!).
Another way could be to use a template function like
template<class T> T operator()(QByteArray const& ba)
template<class T> T operator()(QString const& str)
but T could only be of a few 'supported' type (QByteArray and QVector), therefore user could run into trouble if using wrong T Type. This version seems to be error prone.
So my questions are:
1. Why is the return type of function objects not taken into account in the signature to distinguish between different flavors of the function like in 'classical' functions?
2. Is there a better way around than adding an additional dummy argument?
Thank you for your valuable time.
Alain
Return type is never used for overload resolution. In fact, you can't even declare two functions that differ only in return type. In my opinion, adding this feature would be complicated and not that helpful. Is it necessary to use the function call operator? You could just use a named member function, and then give them different names. Another option would be to use a member template, but even then you would need to explicitly give the return type as a template argument, and the syntax would be ugly if done on the function call operator.
The comment from Kerrek SB suggests a workaround by leveraging conversion operators, if you are okay with something that is complex on the inside, but simpler on the outside.
#include <iostream>
struct A {};
struct B {};
A fooA_impl(const char *) {
std::cerr << "A impl" << std::endl;
return A();
}
B fooB_impl(const char *) {
std::cerr << "B impl" << std::endl;
return B();
}
class Helper {
public:
operator A() { return fooA_impl(p); }
operator B() { return fooB_impl(p); }
private:
friend Helper foo(const char *p);
Helper(const char *p_) : p(p_) {}
const char *const p;
};
Helper foo(const char *p) {
return Helper(p);
}
int
main() {
A a(foo("hello"));
B b(foo("hello"));
}
You can't use overload by return type. One thing you can do is to add the return type as a tag parameter when overloading operator():
QByteArray operator()(QByteArray const& data, const QByteArray& tag );
QVector<quint32> operator()(QByteArray const& data, const QVector<quint32>& tag);
The below is how you call these function:(assume both types have default constructors).
(data, QByteArray());
(data, QVector<quint32>());

Vector of pointer to member functions

I'm trying to write a program which creates a class that contains vector of pointers to member functions, with add() and remove() member functions.
The code I wrote is -
#include <iostream>
#include <vector>
using namespace std;
typedef void(*classFuncPtr)();
class FunctionVectors
{
private:
vector<classFuncPtr> FunctionPointerVector;
public:
FunctionVectors(){}
void add(classFuncPtr funcPtr);
void remove(int index);
void run();
void a(){cout<<"a: Why are you calling me?"<<endl;}
};
void FunctionVectors::add(classFuncPtr funcPtr)
{
FunctionPointerVector.push_back(funcPtr);
}
void FunctionVectors::remove(int index)
{
FunctionPointerVector.erase(FunctionPointerVector.begin() + index);
}
int main()
{
FunctionVectors f;
classFuncPtr fv = &(classFuncPtr)FunctionVectors::a; // error here
f.add(fv);
f.run();
return 0;
}
But, it is showing error in line# 32 -
error C2440: 'type cast' : cannot convert from 'void (__thiscall FunctionVectors::* )(void)' to 'classFuncPtr'
Please, tell me how should I modify it to work properly.
typedef void(*classFuncPtr)();
This is not a pointer to method, but a pointer to function. Method differs from function, because it's being called in a context: requires this to work correctly.
Keep in mind, that in C++ you are only able to create vector of pointers to a method of specific class. So you won't be able to keep pointers to two methods of different classes in that vector.
The solution - as suggested in comments - is to use std::function or boost::function and possibly C++11 lambdas, because they provide a lot more flexibility than simple pointer-to-members.
If you want to implement an event mechanism, consider also using functors instead of methods:
Create base class for event handler:
class MyEventHandler
{
public:
virtual void operator()(void * sender, int data) = 0;
}
Create simple vector of these:
std::vector<MyEventHandler *> MyEvent;
Create specific handlers in your classes:
class MyClass
{
private:
class SpecificEventHandler : MyEventHandler
{
public:
void operator()(void * sender, int data)
{
std::cout << "Event handled!";
}
}
public:
SpecificEventHandler Handler;
MyClass()
{
}
}
Hook the handler to your event:
MyEvent.push_back(&(myClassInstance.Handler));
Code written from memory, may not compile, but you should get the idea.
std::function< void() >
looks like the signature you are looking for. If it isn't available in your version of C++ but you can use boost, then you fill find it in boost. Look up documentation for appropriate header, for std, for function.
To create one for a member function, you need to bind it, and to bind it to FunctionVectors::a() you will need an instance of a FunctionVectors to call it on.
In your example, I will make the typedef for you
typedef std::function< void() > classFuncPtr; // in reality a badly named typedef
int main()
{
FunctionVectors f;
classFuncPtr fv = std::bind( &FunctionVectors::a, f );
}
alternatively if you really have C++11 with lambdas you can do
classFuncPtr = [ f ]() { f.a() );
In your case I reckon you don't really want a free function, you always want a member function of your class you want.
typedef void (*FunctionVectors::classFuncPtr )();
and you would use
(this->*func)();
to invoke it

Pointers to functions

I have to pass function into pointer. For this purposes I'm using boost::function. The function which catches the pointer is overloaded for different signatures. For example:
void Foo(boost::function<int ()>) { ... }
void Foo(boost::function<float ()>) { ... }
void Foo(boost::function<double ()>) { ... }
Now I wanna pass some class-method pointer there:
class test
{
public:
float toCall() { };
};
class Wrapper
{
Wrapper() {
test obj;
Foo(boost::bind(&test::toCall, this));
}
};
error: no matching function for call to ‘Foo(boost::_bi::bind_t<float, boost::_mfi::mf0<float, test>, boost::_bi::list1<boost::_bi::value<Wrapper*> > >)’
note: candidates are: Foo(boost::function<float()>&)
Nonono this cannot work. Because boost::function<...> has a templated constructor to accept any and all types. Compatibility with the call signature is checked later on. Overload resolution cannot resolve this.
Also, i think you want to pass &obj instead of this. Try converting explicitly:
Foo(boost::function<float ()>(boost::bind(&test::toCall, &obj)));
This is utterly ugly though so you may want to introduce a typedef
void Foo(FloatHandler) { ... }
...
FloatHandler f(boost::bind(&test::toCall, &obj));
Foo(f);
Or ultimately you could make Foo a template that accepts just any callable type T. I suspect that may be the simplest, because in the general case i suspect you don't know to what boost::function<...> you need to cast to. And how about folks that want to return a std::complex<>. So...
template<typename T>
void Foo(T) { ... }
...
Foo(boost::bind(&test::toCall, &obj));
Hope this helps.
In the line
Foo(boost::bind(&test::toCall, this));
this is of type Wrapper. But the bind can't find a toCall method on it.
Here's a fixed-up version (complete, compiles on g++ 4.3.2) which is probably what you're trying to do:
#include <boost/bind.hpp>
#include <boost/function.hpp>
void Foo(boost::function<int()>) {}
void Foo(boost::function<float()>) {}
void Foo(boost::function<double()>) {}
struct test {
float toCall() {return 0.0f;}
};
int main(int,char**) {
test obj;
boost::function<float()> tgt=boost::bind(&test::toCall,obj);
Foo(tgt);
return 0;
}
As AndreyT's answer notes, the return type of bind is... a bit odd, hence the explicit coercion to an appropriate function type.
boost::bind does not return a boost::function object. It returns an object of unspecified type that can be used as a functor with corresponding number of parameters.
While boost::function can be conversion-constructed from the result of boost::bind, the overload resolution in this case is "too complex" for C++. (Removed my bad example which didn't really illustrate the right problem).