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

标签 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 及其所有 friend 的意义何在?我的意思是简单的函数对象可以在没有任何工具的情况下被轻松调用,但我认为 std::invoke 的主要目的是概括和简化所有可调用对象的工作,包括棘手的可调用对象,如指向成员的指针。 std::invoke 无法调用明确可调用的目标这一事实对我来说似乎很奇怪。

最佳答案

问题是 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 意味着当您只想获取其他数据成员时,您会遇到与其他数据成员不一致的情况。

关于c++ - 指向 std::invoke 中成员函数对象的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51463561/

相关文章:

c++ - 空检查空对象模式

c++ - 使用C++获取函数内部的数组大小

c++ - 如何避免 C 库中的函数名称冲突?

c++ - 将现代函数接口(interface)写入 "produce a populated container"

c++ - 有没有一种干净的方法可以将重载集转换为适合与 std::visit 一起使用的访问者?

C++17 结构化绑定(bind)和 move 语义

c++ - Fstream 按字符读取 while

c++ - 为什么 std::function 在签名中接受 this 引用?

c++ - 在通用 lambda 中使用 `if constexpr` 访问成员类型需要两个分支的格式都正确 - gcc 与 clang

c++ - 比较来自外部 API 的相同类型的两个结构