指向std :: invoke中成员函数对象的指针

时间:2018-07-22 09:09:35

标签: c++ c++17

为什么std :: invoke不能使用指向具有参数的函数对象的成员的指针?像这样:

struct MyClass
{
    std::function<void(int)> functor{ [](int arg) { printf("%d\n", arg); } };
};
int main()
{
    MyClass mc;
    std::invoke(&MyClass::functor, mc, 110);
}

打印:'std::invoke': no matching overloaded function found. 我在Visual C ++和g ++中对此进行了检查。

此外,std::is_invocable_v<decltype(&MyClass::functor), MyClass, int>声称此仿函数不是不可调用的,这肯定是错误的。 我是否缺少某些东西或它是标准的缺陷?如果这种行为是正确的,那么std :: invoke及其所有朋友的意义何在?我的意思是简单的函数对象可以很容易地调用而无需任何便利,但是我虽然std :: invoke的主要目的是概括和简化所有可调用对象(包括棘手对象,如指向成员的指针)的使用。 std :: invoke无法调用清晰可调用的目标这一事实在我看来很奇怪。

1 个答案:

答案 0 :(得分:4)

问题在于functor不是函数,而是数据成员。因此,&MyClass::functor不是指向成员函数的指针,而是指向成员数据的指针。这种区别意味着您无法将任何其他参数传递给std::invoke,因为您无法调用数据成员;但是对于某些数据成员,例如您的functor,可以。在C ++ 11之前,该标准尚不明确,因此LWG issue 1520已在C ++ 11中合并。

我的意思是您可以将示例重写为:

std::invoke(&MyClass::functor, mc)(110);
// or for maximum confusion
std::invoke(std::invoke(&MyClass::functor, mc), 110);

但我不认为这就是您想要的。 Thanks to Barry,这是个坏主意,因为以下代码会做什么:

struct X {
  std::function<void()> f;
};
std::invoke(&X::f, x); // gets f, or calls f?

获取f使其与其他数据成员一致,但是如果f不带参数,则无法调用f。调用f意味着您只想获取其他数据成员时就会出现不一致的情况。