Почему не работает тип указателя на функцию?

Рейтинг: 3Ответов: 3Опубликовано: 27.01.2023
#include <iostream>

using namespace std;

void func() {
    cout << "call func" << endl;
}

struct S {
    void(*)() operator () () {
        return func;
    }
};

int main() {
    S s;
    s()();
}

Получаю ошибку: error: expected member name or ';' after declaration specifiers
Почему не работает void(*)() в качестве типа возврата?

Любым другим способом тип добавить можно, например, через auto, или через function<void()> или через typedef void(*ptf)();
Но почему нельзя явно указать сам тип??

Ответы

▲ 6Принят

Синтаксис возврата функции в C/C++ очень мудрёный. Допустим вы хотите вернуть другую функцию

double func2 ( int x ) {
  return x + 1 ;
}

тогда синтаксис будет такой :

double ( & operator ( ) ( ) ) ( int ) {
    return func2 ;
}

тип возвращающий возвращаемой функции double
тип аргументов возвращаемой функции int
обрамление скобками со амперсантом ( & operator ( ) ( ) ) означает, что оператор возвращает ссылку на функцию типа double ( & ) ( int )

Можете возвращать не ссылку, а указатель. Никакой разницы.

Проще сначала задать тип, чтобы не путаться :

typedef double TF ( int ) ;
TF & operator ( ) ( ) { 
  return func2 ;
}

в стандарте C++11 можно так :

auto operator ( ) ( ) -> double ( & ) ( int ) {
    return func2 ;
}

в вашем примере :

void ( & operator ( ) ( ) ) ( ) {
    return func ;
}

или

typedef void TF ( void ) ;
TF & operator ( ) ( ) {
    return func ;
}

или стандарт C++11

auto operator ( ) ( ) -> void ( & ) ( ) {
    return func ;
}
▲ 3

На более простом примере.

  • Неправильно: int[10] a = ...;
  • Правильно: int a[10] = ...;
  • Неправильно: void (*)() a = ...;
  • Правильно: void (*a)() = ...;

Ну и аналогично:

  • Неправильно: void(*)() operator()() {...}
  • Правильно: void(*operator()())() {...}
▲ -1

Вот еще несколько примеров:

// Синтаксис возврата для функции func1():
void func1() { ... }                                        // функция типа void(*)()

void ( *operator()() ) () { return func1; }                 // используя перегрузку оператора () вызова функции

auto operator()() { return func1; }                         // используя auto

auto operator()() -> void(*)() { return func1; }            // используя auto c явным указанием типа функции

std::function<void()> operator()() { return func1; }        // используя std::function

typedef void(*PTF)();                                       // using PTF = void(*)();       
PTF operator ()() { return func1; }                         // используя typedef function pointer

typedef void TF (void);                                     // using TF = void (void);      
TF * operator ()() { return func1; }                        // используя typedef function

// Синтаксис возврата для функции func2():
double func2(int x) { ... }                                 // функция типа double(*)(int)

double ( *operator()() ) (int) { return func2; }            // используя перегрузку оператора () вызова функции

auto operator()() { return func2; }                         // используя auto

auto operator()() -> double(*)(int) { return func2; }       // используя auto c явным указанием типа функции

std::function<double(int)> operator()() { return func2; }   // используя std::function

typedef double(*PTF)(int);                                  // using PTF = double(*)(int);  
PTF operator ()() { return func2; }                         // используя typedef function pointer

typedef double TF (int);                                    // using TF = double (int); 
TF * operator ()() { return func2; }                        // используя typedef function