Can anyone help me implement the function test
below, so that it accepts any Callable
and an std::function
and returns true
if the std::function
's target is the Callable? I have been trying various things, but none of them work all the time and I can't even figure out for any of them why they work for the cases that they do work.
#include <type_traits>
#include <iostream>
#include <functional>
int foo(int) {return 0;}
int faz(int) {return 0;}
struct {
int operator()(int) {return 0;}
} bar, baz;
template<class F1, class F2>
bool
test(F1&& f1, std::function<F2> f2) {
//return f2.template target<F1>() == f1;
//return f2.template target<F2>() == &f1;
//return *f2.template target<std::add_pointer_t<F1>>() == &f1;
//return *f2.template target<std::add_pointer_t<F2>>() == &f1;
//return *f2.template target<std::add_pointer_t<F1>>() == f1;
//...
}
int main() {
std::function<int(int)> f{foo};
std::cout << test(foo, f) << std::endl;
std::cout << test(faz, f) << std::endl;
f = bar;
std::cout << test(bar, f) << std::endl;
std::cout << test(baz, f) << std::endl;
}
(http://coliru.stacked-crooked.com/a/11346a171199af81)
If a std::function contains no target, it is called empty. Invoking the target of an empty std::function results in std::bad_function_call exception being thrown. std::function satisfies the requirements of CopyConstructible and CopyAssignable.
The stored callable object is called the target of std::function. If a std::function contains no target, it is called empty. Invoking the target of an empty std::function results in std::bad_function_call exception being thrown. std::function satisfies the requirements of CopyConstructible and CopyAssignable.
Get pointer to target Returns a pointer to the callable objectstored in the functionobject. Because functionis a polymorphic wrapper class, it is unaware of the static type of its target callable object, and thus the template parameter TargetTypemust be explicitly specified.
template<class F1, class F2>
bool test(F1&& f1, std::function<F2> f2) {
auto* ptr = f2.template target<std::decay_t<F1>>();
if (!ptr) return false;
return *ptr == f1;
}
This won't work for lambdas, because lambdas have no operator==
.
This won't work for your struct, because it has no operator==
.
It will work for function pointers, because they do have an operator==
.
struct bob {
int operator()(int) {return 0;}
bool operator==(bob const& o)const{return true;}
} bar, baz;
now it works. Of course, both bar
and baz
compare equal to any bob
.
Now, function stores a copy of anything you pass it. So you cannot compare the address of the function stored in function to the address of the thing it copied from and get a useful result.
std::ref
wraps a pointer up to act reference like.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With