首页 > 解决方案 > 用 constexpr 对象的函数指针成员函数初始化 std::array

问题描述

我正在尝试初始化函数指针的 std::array 。这些指针指向已实例化对象的成员函数。

有人可以帮忙看看下面的例子吗?提前谢谢了!

#include <array>

using TVoidVoid = void (*)(void);

class Foo {
public:
  constexpr Foo() {}
  void myHandler() {}
};

class Bar {
public:
  constexpr Bar() : handler_{nullptr} {}
  constexpr Bar(TVoidVoid handler) : handler_{handler} {}

private:
  TVoidVoid handler_;
};

Foo f;
std::array<Bar, 5> bar_array = {{Bar{}, Bar{f.myHandler}}};

int main() {}

编译产生:

main.cpp:22:56: error: no matching function for call to ‘Bar::Bar(<brace-enclosed initializer list>)’
std::array<Bar, 5> bar_array = {{Bar{}, Bar{f.myHandler}}};

我正在使用g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0.

标签: c++c++14

解决方案


指向自由函数的指针的处理方式与指向成员函数的指针不同。TVoidVoid类型是指向自由函数的指针,但您需要指向成员函数的指针Foo。因此,Foo首先定义,

class Foo { /* As before... */ };

然后使用成员函数的类型别名(Foo此时必须知道)

// Note the different syntax to the former TVoidVoid
using FooVoidVoid = void (Foo::*)();

接下来,Bar必须调整它的数据成员是类型FooVoidVoid,并且构造函数接受这个类型作为参数(其余的Bar可以保持原样),最后将数组定义为

std::array<Bar, 3> bar_array = {{Bar{}, Bar{&Foo::myHandler}}};

请注意,这与任何现有实例&Foo::myHandler无关。Foo它只是一个指向Foo成员函数的指针,只有当你调用它时,它才必须与一个Foo对象(特殊运算符.*->*旨在实现这一点,或者std::invoke在升级到支持 C++17 的编译器后使用) )。


推荐阅读