Ответ 1
Рассмотрим этот пример:
struct s {
void test1();
void(*test2)();
void(**test3)();
};
int main() {
static_assert(test<decltype(&s::test1)>::value == 1);
static_assert(test<decltype(&s::test2)>::value == 2);
static_assert(test<decltype(&s::test3)>::value == 3);
auto test4 = &s::test1;
static_assert(test<decltype(&test4)>::value == 4);
auto test5 = &test4;
static_assert(test<decltype(&test5)>::value == 5);
}
Вот типы:
R(C::*)(Args...)
- указатель на функцию-член. R(*C::*)(Args...)
- указатель на элемент данных, который является указателем на функцию. R(**C::*)(Args...)
- указатель на элемент данных, который является указателем на указатель функции. R(C::**)(Args...)
- указатель на указатель на функцию-член. R(C::***)(Args...)
- указатель на указатель на указатель на функцию-член.
Чтобы вызвать их, рассмотрите слегка измененный пример:
struct s {
void test1() {std::cout << "test1\n";}
void(*test2)() = [] {std::cout << "test2\n";};
void(*test3Helper)() = [] {std::cout << "test3\n";};
void(**test3)() = &test3Helper;
void test4() {std::cout << "test4\n";}
void test5() {std::cout << "test5\n";}
};
int main() {
s obj;
auto test4 = &s::test4;
auto test5Helper = &s::test5;
auto test5 = &test5Helper;
(obj.*(&s::test1))();
(*(obj.*(&s::test2)))(); // note that the dereference is unnecessary
(**(obj.*(&s::test3)))(); // note that the second dereference is unnecessary
(obj.**(&test4))();
(obj.***(&test5))();
}
Обратите внимание, что в каждом случае, если у вас есть переменная со значением соответствующего &[s::]testN
, вы можете заменить (&[s::]testN)
на эту переменную. Также обратите внимание, что для test2 и test3 я разыменован до тех пор, пока функция не вернется, а не указатель функции для иллюстрации.