In C++0x, we use use std::function like the following:
int normal_function() {
return 42;
}
std::function<int()> f = normal_function;
So to get an std::function instance, we have to define its type firstly. But it's boring and sometimes hard.
So, can we just use make to get a std::function instance just like std::tuple?
In fact, I just googled, C++0x doesn't provide such make facility.
Why C++0x no provide make facility?
Can we implement it?
Yes we can implement it
template<typename T>
std::function<T> make_function(T *t) {
return { t };
}
This requires that you pass a function to make_function. To prevent overload to pick this up for something other than a plain function, you can SFINAE it
template<typename T>
std::function<
typename std::enable_if<std::is_function<T>::value, T>::type
> make_function(T *t) {
return { t };
}
You cannot pass it class type function objects though and no member pointers. For arbitrary function objects there is no way to obtain a call signature (what would you do if the respective operator() is a template?). This probably is the reason that C++11 provides no such facility.
Related
This is kind of a follow up to this question, where I asked how I could tersely turn a template and/or overloaded function into a function object.
The accepted answer was you can't do without macro, which is correct. Then I found that such a macro is offered by Boost, in the form of the BOOST_HOF_LIFT and BOOST_HOF_LIFT_CLASS macros.
It turns out, however, that there are other "named things" you can't pass around. I don't know all of them, but one of them is constructors. And Boost.Hof offers a way to lift them to, via boost::hof::construct.
The point is that not even boost::hof::construct can deal with a class without a user-declared constructor. For intance, given
struct Foo {
int foo;
};
the call boost::hof::construct<Foo>()(3) simply doesn't work. (Adding the constructor Foo(int) {} in Foo makes it work; that's what boost::hof::construct is for, after all.)
Surely, in simple cases like the one above I could just write
auto makeFoo = [](int x){ return Foo{x}; };
but if I want to support any type, I have to take care of perfect forwarding and variadic arguments.
Is there a library offering this feature already? It doesn't look like Boost.Hof does...
If you want a function object that constructs an object of some type T given some parameters, even if T is an aggregate, that's not difficult to write in C++17:
template<typename T>
struct lifted_construct
{
template<typename ...Args>
T operator() (Args&& ...args)
{
if constexpr(std::is_aggregate_v<T>)
{
return T{std::forward<Args>(args)...};
}
else
{
return T(std::forward<Args>(args)...);
}
}
};
Of course, in C++20, you can use () syntax even for aggregates.
I want to declare std::unique_ptr with custom deleter, which binds some arguments to the specific function:
using namespace std::placeholders;
using HandleDeleter = std::invoke_result_t<std::bind, _1, SOME_FLAG>; // !!!
using HandlePtr = std::unique_ptr<handle_t, HandleDeleter>;
void handle_destroy(handle_t *, int flags);
handle_t * raw_handle;
auto deleter = std::bind(handle_destroy, _1, SOME_FLAG);
HandlePtr ptr(raw_handle, deleter);
And this doesn't work because std::bind is a monstrous template construction on its own with unspecified return type.
How to properly declare HandleDeleter in my case?
std::bind is not a single callable, but a function-template. Thus, you would have to choose which one to pass to std::invoke_result_t, which is really messy.
Fortunately, there are better alternatives:
Use decltype:
using deleter_t = decltype(std::bind(handle_destroy, _1, SOME_FLAG));
Use template-argument-deduction for the class:
unique_ptr ptr(raw_handle, deleter);
Anyway, not using std::bind() is generally simpler, as well as more efficient due to hard-coding the function and argument used. Though you certainly are free to only hard-code part:
Use a lambda instead of std::bind(). In C++20 a stateless lambda will even become default-constructible:
auto deleter = [](handle_t* p){ handle_destroy(p, SOME_FLAG); };
Define your own custom deleter-class instead of using std::bind:
struct deleter_t {
constexpr void operator()(handle_t* p) const noexcept {
handle_destroy(p, SOME_FLAG);
}
};
And this doesn't work because std::bind is a monstrous template construction on its own with unspecified return type.
This is a hint: you're probably using the wrong tool for the job.
I would use a simple struct instead:
struct HandleDeleter
{
int _flag;
void operator()(handle_t* h) const
{
handle_destroy(h, _flag);
}
};
HandlePtr ptr(raw_handle, HandleDeleter{SOME_FLAG});
std::bind is not recommended in Modern C++. Use lambdas (or structs) instead. std::bind has several issues excellently explained in this talk by Stephan T. Lavavej “functional: What's New, And Proper Usage".
I recently wrote about the function of class member function callbacks. I need to save the callback object and function pointer, then call the function pointer and fill in the appropriate parameters where the callback is needed.
I started out as a form of typedef void (AAA::*Function)(int a, int b);, but when I need to support different parameter lists of member function, I obviously need a dynamic way to implement it.
class AAA
{
public:
int add(int a, int b)
{
return (a + b);
}
};
class BBB
{
public:
void setValue(std::string value)
{
this->value = value;
}
private:
std::string value;
};
class CCC
{
public:
void bind(??? p) // Binding objects and callback functions.
{
this->p = p;
}
template <class... Args>
auto callback(Args&&... args) // Autofill parameter list.
{
return this->p(std::forward<Args>(args)...);
}
private:
??? p; // How is this function pointer implemented?
};
int main()
{
AAA aaa;
BBB bbb;
CCC ccc;
ccc.bind(???(aaa, &AAA::add));
int number = ccc.callback(5, 6);
ccc.bind(???(bbb, &BBB::setValue));
ccc.callback("Hello");
system("pause");
return 0;
}
I don't know how can I implement the function pointer "???".
You basically are asking to have fully dynamicly typed and checked function calls.
To have fully dynamic function calls, you basically have to throw out the C++ function call system.
This is a bad idea, but I'll tell you how to do it.
A dynamicly callable object looks roughly like this:
using dynamic_function = std::function< std::any( std::vector<std::any> ) >
where use use
struct nothing_t {};
when we want to return void.
Then you write machinery that takes an object and a specific signature, and wraps it up.
template<class R, class...Args, class F>
struct dynamic_function_maker {
template<std::size_t...Is>
dynamic_function operator()(std::index_sequence<Is...>, F&& f)const {
return [f=std::forward<F>(f)](std::vector<std::any> args)->std::any {
if (sizeof...(Is) != args.size())
throw std::invalid_argument("Wrong number of arguments");
if constexpr( std::is_same< std::invoke_result_t<F const&, Args... >, void >{} )
{
f( std::any_cast<Args>(args[Is])... );
return nothing_t{};
}
else
{
return f( std::any_cast<Args>(args[Is])... );
}
};
}
dynamic_function operator()(F&& f)const {
return (*this)(std::make_index_sequence<sizeof...(Args)>{}, std::forward<F>(f));
}
};
template<class R, class...Args, class F>
dynamic_function make_dynamic_function(F f){
return dynamic_function_maker<R,Args...,F>{}(std::forward<F>(f));
}
next you'll want to deduce signatures of function pointers and the like:
template<class R, class...Args>
dynamic_function make_dynamic_function(R(*f)(Args...)){
return dynamic_function_maker<R,Args...,F>{}(std::forward<F>(f));
}
template<class Tclass R, class...Args>
dynamic_function make_dynamic_function(T* t, R(T::*f)(Args...)){
return dynamic_function_maker<R,Args...,F>{}(
[t,f](auto&&...args)->decltype(auto){return (t->*f)(decltype(args)(args)...);}
);
}
then after fixing typos above you should be able to solve your original problem.
Again, as someone who can actually write and understand the above code, I strongly advise you not to use it. It is fragile and dangerous.
There is almost never a good reason to store callbacks in places where you don't know what the arguments you are going to call it with.
There should be a different type and instance of CCC for each set of arguments you want to call it with. 99/100 times when people ask this question, they are asking the wrong question.
C++ is a type-safe language. This means that you cannot do exactly what you've outlined in your question. A pointer to a function that takes specific parameters is a different type from a pointer to a function that takes different parameters. This is fundamental to C++.
std::bind can be use to type-erase different types to the same type, but you get a single type at the end, that can be called only with a matching set of parameters (if any). It is not possible to invoke the "underlying" bound function, with its real parameters. That's because the whole purpose of std::bind is to make them disappear, and inaccessible. That's what std::bind is for.
You only have a limited set options to make this work while staying with the bounds and constraints of C++'s type-safety.
Make use of a void *, in some fashion. Actually, don't. Don't do that. That will just cause more problems, and headache.
Have a separate list and classes of callbacks, one list for each set of callbacks that take a specific set of parameters. You must know, at the point of invoking a callback, what parameters you intend to pass. So, just get your callback from the appropriate list.
Make use of std::variant. The type-safe std::variant is C++17 only (but boost has a similar template that's mostly equivalent, and available with older C++ revisions). All your callbacks take a single std::variant parameter, a variant of every possible set of parameters (designated as a std::tuple of them, or some class/struct instance). Each callback will have to decide what to do if it receives a std::variant containing the wrong parameter value.
Alternatively, the std::variant can be a variant of different std::function types, thus shifting the responsibility of type-checking to the caller, instead of each callback.
The bottom line is that C++ is fundamentally a type-safe language; and this is precisely one of the reasons why one would choose to use C++ instead of a different language that does not have the same kind of type-safety.
But being a type-safe language, that means that you have certain limitations when it comes to juggling different types together. Specifically: you can't. Everything in C++ is always, and must be, a single type.
I am trying to do the following, and I am not even sure if it's possible.
I want a function that takes in an arbitrary function pointer to pass it to a different function (I am aware this is a code smell, good software engineering practices are not what I want to discuss right now).
In other words what I am looking for would look like:
void method1(arbitraty pointer p)
{
method2(p);
}
I am not sure if there is a way to declare arbitrary function pointers (the return value is guaranteed to be void but the parameters are arbitrary, both in number and type)
Use template and use SFINAE to enable it only if the type deduced is a function pointer type:
template <typename T, std::enable_if_t<std::is_function<T>::value, int> = 0>
void method1(T* p)
{
// ...
}
This might be considered over-engineering by some, but you could try the following:
Create an enum of each callback that you are interested in:
enum GlfwCallback {
KeyCallback,
FramebufferSizeCallback,
// etc.
};
Then create a type family that associates each of these with the corresponding function pointer type. Do this by creating a template struct and repeatedly specializing it:
template<GflwCallback callback>
struct GlfwCallbackType {};
template<>
struct GlfwCallbackType<KeyCallback> {
using CallbackType = GLFWkeyfun;
// or
using CallbackType = void(*)(GLFWwindow *, int, int, int, int);
};
template<>
struct GlfwCallbackType<FramebufferSizeCallback> {
using CallbackType = GLFWframebuffersizefun;
};
// etc.
Then you can write
template<GlfwCallback callback>
void method1(GlfwCallbackType<callback>::CallbackType p) {
// do something with p
method2<callback>(p);
};
Also, note that you can add other types and even static functions and data members to your "type family" as needed by your application.
A possibility to do what you want, but in a nice, type-safe fashion, would be the use of functors, i.e. classes that define an overloading for the operator().
Since a functor is a class, you could set the arguments as data memebers, and move the implementation/calling of the functions that you want to pass as arbitrary pointers into the operator() method, where you can have access to all the parameters through the this pointer.
Furthermore, you can define a hierarchy of functors, each one with specialized parameters and implementations, so you can modify the signature of method2 like the following:
method2(BaseFunctor* myfunctor) {
if (myfunctor)
(*myfucntor)();
}
and setup the right type of functor object in the calling context.
Also check out lambdas (c++11), that are basically a shortcut to functors definition.
I have a one-dimensional function minimizer. Right now I'm passing it function pointers. However many functions have multiple parameters, some of which are held fixed. I have implemented this using functors like so
template <class T>
minimize(T &f) {
}
Functor f(param1, param2);
minimize<Functor>(f);
However the functor definition has lots of crud. Boost::bind looks cleaner. So that I could do:
minimize(boost:bind(f,_1,param1,param2))
However I'm not clear what my minimize declaration should like like using boost::bind. What type of object is boost::bind? Is there an easy pattern for this that avoids the boilerplate of functors but allows multiple parameter binding?
You can just use boost::function. I think boost::bind does have its own return type, but that is compatible with boost::function. Typical use is to make a typedef for the function:
typedef boost::function<bool(std::string)> MyTestFunction;
and then you can pass any compatible function with boost::bind:
bool SomeFunction(int i, std::string s) { return true; }
MyTestFunction f = boost::bind(SomeFunction, 42, _1);
f("and then call it.");
I hope that is what you want.
It also works with methods by passing the this pointer for the call as second parameter to boost::bind.
I would define minimize() this way:
minimize(boost::function< return_type(param_type1,param_type2,param_type3,...)> f)
{
...
}
Then you could call minimize() like this:
minimize(boost::bind(&class::function,actual_object,_1,_2,_3,...));
Change the parameter to a value parameter. Function objects are intentionally light weight, and boost::bind certainly is, specially crafted to fit in within space of a few bytes using boost::compressed_pair and what not.
template <class T>
void minimize(T f) {
}
Then you can pass it the result of boost::bind. Remember that boost::bind is actually a function template that returns some object of some type. So having minimize have a non-const reference parameter couldn't work.
First, you are taking your template argument as a ref-to-non-const, so the temporary returend by boost::bind won't bind to it. So you can use it like:
template <class T>
T::result_type minimize(const T &f) {
}
But if you wanted to use this with your Functors as well, they would have to have a const operator(). So perhaps by value is better:
template <class T>
T::result_type minimize(T f) {
}
I believe having the return be T::result_type will force a T to be a boost::function (rather than the complicated type bind returns), but I'm not 100%