I've always had difficulty understanding the std::function
template. It seems to use magic that I don't know yet. It's template arguments are class R
, class... ARGS
. Yet it can be passed to the template as std::function<void>
or std::function<void()>
. An example with parameters: std::function<void, int, float>
or std::function<void(int, float)>
. Was this 2nd syntax introduced in c++11 ? I don't think this was valid prior.
Also, is there a way to get the decltype
of a function and pass it to the function template? It would make setup of the function template so much easier.
Here is an example:
#include <functional>
using namespace std;
///////////////////////////////////////////////////////////////////////////////
// this works
void x() {}
void y(int p0) {}
int main1()
{
using namespace std::placeholders;
function<decltype(y)> functors[] = { bind(x), bind(y, _1) };
functors[0](1);
functors[1](1);
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// this doesn't work
struct X
{
void x() {}
void y(int p0) {}
void z(int i, int p0)
{
using namespace std::placeholders;
static function<decltype(&X::y)> functors[] = { bind(&X::x, _1), bind(&X::y, _1, _2) };
functors[i](this, p0);
}
};
int main2()
{
X xobj;
xobj.z(0, 1);
xobj.z(1, 1);
return 0;
}
int main()
{
return main1() + main2();
}
std::function
accepts one template argument, which must be a function type. You cannot use std::function<void, int, float>
. std::function<void(int, float)>
is the only valid syntax.
std::function
was introduced in C++11. There's no std::function
prior to that. There was std::tr1::function
though, defined in TR1, which used the same std::function<void(int, float)>
syntax.
The decltype
thing you're looking for is probably something like:
template<typename T>
struct transform_to_free_function;
template <typename Target, typename R, typename... Args>
struct transform_to_free_function<R (Target::*)(Args...)>
{
using type = R(Target*, Args...);
};
Note: 1) type
is now a public
member 2) it should rather be a function type, not a pointer for this purpose. It isn't straightforward to make a non-pointer type from a pointer type, but otherwise you had to use a std::remove_pointer
on it.
The rest of your example then compiles fine:
#include <functional>
using namespace std;
template<typename T>
struct transform_to_free_function;
template <typename Target, typename R, typename... Args>
struct transform_to_free_function<R (Target::*)(Args...)>
{
using type = R(Target*, Args...);
};
struct X
{
void x() {}
void y(int p0) {}
void z(int i, int p0);
};
void X::z(int i, int p0)
{
using namespace std::placeholders;
static function<transform_to_free_function<decltype(&X::y)>::type>
functors[] = { bind(&X::x, _1), bind(&X::y, _1, _2) };
functors[i](this, p0);
}
int main()
{
X xobj;
xobj.z(0, 1);
xobj.z(1, 1);
return 0;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.