Почему определение типа функции нельзя использовать для определения функции?

Из п. 8.3.5.11 ИСО / МЭК 14882: 2011 (E):

Определение типа типа функции может использоваться для объявления функции, но не должно использоваться для определения функции

Стандарт продолжает приводить этот пример:

typedef void F();
F fv; // OK: equivalent to void fv();
F fv { } // ill-formed
void fv() { } // OK: definition of fv

Что мотивирует это правило? Кажется, он ограничивает потенциальную выразительную полезность функции typedefs.

10

Решение

Хотя этот вопрос о C ++, но так как C ++ наследует typedef и указатель на функцию из C, поэтому здесь можно использовать объяснение того же вопроса в C. Есть формальное объяснение C.

Обоснование международного стандарта — Языки программирования C §6.9.1 Определения функций

Список аргументов должен явно присутствовать в деклараторе; это не может быть унаследовано от typedef (см. §6.7.5.3). То есть, учитывая определение:

typedef int p(int q, int r);

следующий фрагмент недействителен:

p funk // weird
{ return q + r ; }

Некоторые текущие реализации переписывают тип, например, char параметр, как если бы он был объявлен intпоскольку известно, что аргумент передается как int в отсутствие прототипа. Стандарт требует, однако, чтобы полученный аргумент был преобразован, как если бы он был назначен при входе в функцию. Переписывание типов, таким образом, больше не допустимо.

12

Другие решения

Это, вероятно, в основном исторические причины. typedef был относительно поздним дополнением к C и был добавлен в существующий язык (и вызвал некоторые проблемы на этапе синтаксического анализа компиляторов).

Кроме того, функция определение должен определить имена параметров, если таковые имеются. Функция тип включает в себя тип возвращаемого значения функции и типы параметров, но не имена ее параметров. Например, эти:

void (int)
void (int x)
void (int y)

три способа написания одного и того же типа функции. Если у тебя есть:

typedef void func_t(int);

тогда это гипотетическое определение:

func_t some_func { }

не будет определять имя для его int параметр. Я не уверен, как это могло быть решено разумным способом. Это было бы возможно, я полагаю, но это никогда не было сделано.

Но суть, вероятно, просто в том, что Деннис Ритчи тоже не думал, что стоит попытаться определить, как typedef может быть использован в определении функции, или он просто не думал об этом.

7

Позвольте мне сказать несколько слов. Рассмотрим утверждение:

typedef void F(int p1, char* p2);

Это утверждение присваивает имя F подписи функции void (int, char*); Это определение псевдонима подписи функции. После этого заявление:

F fv;

говорит, что есть функция fv, У него есть подпись, о которой говорилось выше, и где-то есть его тело. Посмотрите на синтаксис C / C ++ определения функции:

retType  funcName(params) { body }

На самом деле используются 2 имени retType а также funcName, Ни один из них не совпадает с именем F из начального определения типа. Имя F имеет значение обоих имен. Если бы язык позволял что-то вроде:

F { body }

это свяжет тело с типом функции. Но это приводит к проблеме:

Значение F было бы не понятно. Это «псевдоним сигнатуры функции» или «имя точки входа в код»?

Плюс синтаксис последнего примера был бы странным для миллионов программистов на C / C ++.

1

Правило так, как вы цитировали — typedef of function type shall not be used to define a function, В 3-й строке примера вы пытаетесь определить функцию с типом функции F, Это не разрешено стандартом.


РЕДАКТИРОВАТЬ
Как вы указали, я пытаюсь объяснить больше об этом.

Для 3-й строки, если это допустимо, вы можете заменить F на определение typedef:
void fv { }(), Это не юридическое определение или объявление в C ++.

Я думаю, что ключевым моментом является то, что typedef просто создает псевдоним для упрощения, и вы можете заменить свой тип typedef, как замена #define во время компиляции.

-4
По вопросам рекламы [email protected]