首页 > 解决方案 > 将指向数据成员的指针传递给 std::invoke 时有哪些用例和用处?

问题描述

我正在阅读关于cpp 引用的std::invoke并且想知道在哪些情况下我们需要将指向数据成员的指针和对象作为第二个参数作为第一个参数传递。

从 cpp 参考它说明了这一点:

使用参数 args 调用 Callable 对象 f。正如 INVOKE(std::forward(f), std::forward(args)...)。

其中 INVOKE(f, t1, t2, ..., tN) 定义如下:

...

然后第二点是:

否则,如果 N == 1 并且 f 是指向类的数据成员的指针

好的,让我们进一步看一下,假设我正在使用std::thread(哪个构造函数使用std::invoke):

例如,我有点不清楚以这种方式使用线程什么时候有用(或者什么可以强制)?

struct Foo {
    Foo(int num) : num_(num) {}
    void print_add(int i) const { std::cout << num_+i << '\n'; }
    int num_;

    void print_num(int i) const {
        std::cout << i << '\n';
    }
};

int main() {
    const Foo foo(314159);
    std::thread t(&Foo::num_, foo);
    t.join();
    return 0;
}  

以及指向数据成员的指针如何与可调用概念相关联?

标签: c++c++11c++17stdthreadc++-concepts

解决方案


您可能认为只有指向成员函数的指针才有用。也就是说,类似:

struct Widget {
    bool valid() const;
};

std::vector<Widget> widgets;
bool all_valid = std::ranges::all_of(widgets, &Widget::valid);

这将std::invoke指向&Widget::valid每个Widgets 上的成员函数的指针。但是你可以很容易地构造Widget这样valid一个标志而不是成员函数。检查所有的Widgetsvalid是一样合理的事情:

struct Widget {
    bool valid;
};

std::vector<Widget> widgets;
bool all_valid = std::ranges::all_of(widgets, &Widget::valid);

唯一的区别是这个std::invokesa 指向成员数据的指针而不是指向成员函数的指针。但还是有用的。


推荐阅读