Pourquoi l’opérateur () du foncteur sans état ne peut-il pas être statique?

Pourquoi l’ operator () du foncteur sans état n’est-il pas autorisé à être static ? Les objects lambda sans état sont convertibles en pointeurs en fonctions libres ayant la même signature que leur operator () .

Stephan T. Lavavej sur p. 6 fait remarquer que la conversion en un pointeur de fonction n’est qu’un operator FunctionPointer() (cite). Mais je ne peux pas obtenir un pointeur correspondant à operator () quant à la fonction non-membre. Pour la struct F { void operator () () {} } foncteur struct F { void operator () () {} } il semble impossible de convertir &F::operator () en une instance de type using P = void (*)(); .

Code:

 struct L { static void operator () () const {} operator auto () const { return &L::operator (); } }; 

L’erreur est

surchargé ‘operator ()’ ne peut pas être une fonction membre statique

mais operator () n’est pas surchargé.

Par norme 13.5 / 6,

Une fonction opérateur doit être une fonction membre non statique ou une fonction non membre et avoir au moins un paramètre dont le type est une classe, une référence à une classe, une énumération ou une référence à une énumération.

De plus, en 13.5.4, il est indiqué que

operator () doit être une fonction membre non statique avec un nombre arbitraire de parameters. Il peut avoir des arguments par défaut. Il implémente la syntaxe d’appel de fonction postfix-expression (expression-list opt), l’expression postfix-expression étant évaluée à un object de classe et la liste d’expressions éventuellement vide correspondant à la liste de parameters d’une fonction membre operator () de la classe. Ainsi, un appel x (arg1, …) est interprété comme x.operator () (arg1, …) pour un object de classe x de type T

Je penserais qu’il n’ya aucune raison technique d’interdire cela (mais que je ne suis pas familier avec le C ++ ABI (Itanium ABI), fournisseur croisé de facto, je ne peux rien promettre).

Il existe toutefois un problème d’évolution à ce sujet à l’ adresse https://cplusplus.github.io/EWG/ewg-active.html#88 . Il porte même la marque [minuscule] , ce qui en fait un élément “sortingvial” à l’étude.

Je ne vois aucune raison technique d’interdire un static auto operator()( ... ) . Mais comme il s’agit d’un cas spécial, il serait compliqué pour le standard d’append un support. Et une telle complication n’est pas nécessaire, car il est très facile à imiter:

 struct L { static void func() {} void operator()() const { func(); } operator auto () const { return &L::func; } }; 

Voir la réponse de Johannes pour des informations supplémentaires éventuellement utiles.

Une solution de contournement simple et un peu sale jusqu’à ce que le comité compétent considère cette fonctionnalité sortingviale:

Les opérateurs globaux sont syntaxiquement similaires aux constructeurs.

Ainsi, vous ne pouvez pas écrire un

 static MyClass::operator()(...); 

Cela a été rendu tout simplement impossible, car un comité l’a décidé sur des raisons peu claires. Je serais si heureux si je pouvais parler à un de leurs membres, leur demander ce qu’ils pensaient alors qu’ils en avaient décidé ainsi. Malheureusement, il ne comprendrait probablement pas ma question, car il n’a jamais programmé le c ++. Il n’a travaillé que sur sa documentation.

Maintenant, ils ont besoin de quelques décennies de

  • débats
  • consultations
  • des réunions
  • et considérations

mettre en œuvre une fonctionnalité sortingviale. Je pense que cette fonctionnalité est disponible dans c ++ 3x et peut même être essayée sur des machines émulées.

Jusque-là, vous pouvez essayer d’écrire:

 MyClass::MyClass(...); 

Dans les deux cas, vous pouvez appeler MyClass(...); .

Bien sûr, cela est utile principalement si MyClass est un singleton. Et, je dirais que c’est un bidouillage. De plus, il alloue un sizeof(MyClass) sur la stack, ce qui peut être mauvais en sizeof(MyClass) performances / efficacité.


De plus, ce sera essentiellement un constructeur, et les constructeurs ne peuvent rien retourner. Mais vous pouvez éviter cela en stockant le résultat dans l’instance, puis en le transmettant à tout ce que vous souhaitez par un opérateur de casting.