Où dans la norme les fonctions renvoyant des fonctions sont-elles interdites? Je comprends qu’ils sont ridicules sur le plan conceptuel, mais il me semble que la grammaire le leur permettrait. Selon cette page Web, un " noptr-declarator [est] tout déclarateur valide " qui inclurait le déclarateur d'une fonction:
int f()();
Concernant la syntaxe.
Il me semble que la syntaxe, telle qu’elle est décrite dans [dcl.decl], permet
int f(char)(double)
qui pourrait être interprété comme la fonction} _ f
cela prend unchar
et renvoie une fonction avec la même signature queint g(double)
.
1 declarator:
2 ptr-declarator
3 noptr-declarator parameters-and-qualifiers trailing-return-type
4 ptr-declarator:
5 noptr-declarator
6 ptr-operator ptr-declarator
7 noptr-declarator:
8 declarator-id attribute-specifier-seq opt
9 noptr-declarator parameters-and-qualifiers
10 noptr-declarator [ constant-expression opt ] attribute-specifier-seq opt
11 ( ptr-declarator )
12 parameters-and-qualifiers:
13 ( parameter-declaration-clause ) cv-qualifier-seqAfter
Grosso modo, après 1-> 2, 2 = 4, 4-> 6, 4-> 6 Vous devriez avoir Opérateur ptr Opérateur ptr Opérateur ptr Ensuite, utilisez 4-> 5, 5 = 7, 7-> 8 pour le premier déclarant; utilisez 4-> 5, 5 = 7, 7-> 9 pour les deuxième et troisième déclarants.
De [dcl.fct], assez explicitement:
Les fonctions ne doivent pas avoir de type de retour de type tableau ni fonction , bien qu'elles puissent avoir un type de retour de tapez un pointeur ou une référence à de telles choses. Il ne doit pas y avoir de tableaux de fonctions, bien qu'il puisse y en avoir des pointeurs vers les fonctions.
Avec C++ 11, vous voulez probablement juste:
std::function<int()> f();
std::function<int(double)> f(char);
Il y a une certaine confusion concernant la grammaire C++. L'instruction int f(char)(double);
can peut être analysée en fonction de la grammaire. Voici un arbre d'analyse:
De plus, une telle analyse est même significative sur la base de [dcl.fct]/1:
Dans une déclaration
T D
oùD
a la formeD1
(parameter-declaration-clause) cv-qualifier-seqopt
ref-qualifieropt exception-specificationopt attribut-specifier-seqopt
et le type de déclarator-id contenu dans la déclarationT D1
est “Derive-Declarator-Type-ListT
”, le type de déclarator-id dansD
est “derive-declarator-type-list fonction de (parameter-declaration-clause) cv-qualifier-seqoptref-qualifieropt returnT
”.
Dans cet exemple, T == int
, D == f(char)(double)
, D1 == f(char)
. Le type de déclarator-id dans T D1
(int f(char)
) est "fonction de (caractère) renvoyant int". Donc, dérivé-déclarateur-type-liste est "fonction de (char) retournant". Ainsi, le type de f
serait lu comme "fonction de (char) retournant la fonction de (double) retournant int."
C'est finalement beaucoup de bruit pour rien, car il s'agit d'un formulaire de déclaration explicitement interdit. Mais pas par la grammaire.
À moins que vous ne renvoyiez un pointeur ou une référence à une fonction qui soit ok, l’alternative consiste à renvoyer une copie d’une fonction. Maintenant, réfléchissez à quoi une copie d’une fonction ressemble, se comporte, se comporte. Ce serait d’abord un tableau d’octets, ce qui n’est pas autorisé non plus, et le second de tous ces octets serait l’équivalence d’un morceau de code renvoyant littéralement un morceau de code ... presque tous les scanneurs de virus heuristiques considérez qu’il s’agit d’un virus car il n’y aurait aucun moyen de vérifier la viabilité du code renvoyé par le système d’exécution ou même au moment de la compilation. Même si vous pouviez renvoyer un tableau, comment renverriez-vous une fonction? Le principal problème avec le retour d'un tableau (qui serait une copie sur la pile) est que sa taille est inconnue et qu'il est donc impossible de le supprimer de la pile. Le même dilemme existe pour les fonctions (où le tableau serait le code binaire en langage machine). De plus, si vous rendiez une fonction de cette manière, comment la retourneriez-vous et l'appeleriez-vous?
En résumé, la notion de renvoi d'une fonction plutôt que d'un point à une fonction échoue car il s'agit d'un tableau de taille inconnue de code machine placé (copié) sur la pile. Ce n'est pas quelque chose que C ou C++ a été conçu pour permettre, et avec le code, il est maintenant possible de faire demi-tour et d'appeler cette fonction, surtout si vous vouliez passer des arguments.
J'espère que cela a du sens
La grammaire formelle de C interdit en réalité de renvoyer des fonctions, mais on peut toujours renvoyer un pointeur de fonction qui, à toutes fins utiles, semble être ce que vous voulez faire:
int (*getFunc())(int, int) { … }
Je suis obsédé par le fait de dire que la grammaire est une explication plus fondamentale du manque de prise en charge d'une telle fonctionnalité. Les règles de la norme sont une dernière préoccupation.
Si la grammaire ne fournit pas un moyen d'accomplir quelque chose, je ne pense pas que la signification de la sémantique ou de la norme soit importante pour un langage sans contexte donné.