正确使用std :: function :: target

Bar*_*uch 8 c++ c++11 c++17

任何人都可以帮我实现test下面的功能,以便它接受任何Callable和一个std::function并返回true如果std::function目标是可调用?我一直在尝试各种各样的事情,但它们都没有一直在工作,我甚至无法弄清楚为什么他们为他们工作的案件工作.

#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;
}
Run Code Online (Sandbox Code Playgroud)

(http://coliru.stacked-crooked.com/a/11346a171199af81)

Yak*_*ont 6

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;
}
Run Code Online (Sandbox Code Playgroud)

这不适用于lambdas,因为lambdas没有operator==.

这对你的结构不起作用,因为它没有operator==.

它适用于函数指针,因为它们确实有operator==.

struct bob {
  int operator()(int) {return 0;}
  bool operator==(bob const& o)const{return true;}
} bar, baz;
Run Code Online (Sandbox Code Playgroud)

现在它有效.当然,无论barbaz比较等于任何bob.

现在,函数存储您传递的任何内容的副本.因此,您无法将函数中存储的函数的地址与其复制的函数的地址进行比较,并获得有用的结果.

std::ref 将指针包起来作为参考.