Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using std::function::target correctly

Tags:

c++

c++11

c++17

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)

like image 971
Baruch Avatar asked Jan 10 '18 10:01

Baruch


People also ask

What happens if a function has no target?

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.

What is the target of an empty function?

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.

What does get pointer to target do in C++?

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.


1 Answers

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.

like image 124
Yakk - Adam Nevraumont Avatar answered Nov 15 '22 12:11

Yakk - Adam Nevraumont