8
votes

Déduire le paramètre de modèle de type non-type

est-il possible de déduire un paramètre de modèle non de type à partir d'un paramètre de fonction de modèle?

Considérez ce modèle simple: P>

factorial(5);


5 commentaires

Pourquoi voudriez-vous faire cela? La fonction factorielle n'accepte aucun paramètre. Quel est l'avantage de factorial (5) sur le bon factorial <5> () ?


@Codygray: Je pense que l'idée serait de créer une fonction générique factorielle capable de calculer le résultat au moment de la compilation s'il reçoit une expression hélice de la compilation, mais aussi capable de le calculer au moment de l'exécution. Si l'entrée est une variable normale.


@Matteo: Autant que je sache, rien n'est calculé au moment de l'exécution, car l'expression est déclarée consexpr . Et de toute façon, je ne comprends pas pourquoi il y aurait un problème de passage d'une "variable normale" au lieu des 5 à l'aide de la syntaxe standard. La question ici est "Comment puis-je éviter de taper des crochets d'angle" et je ne comprends pas la motivation.


Je veux éviter de devoir changer beaucoup de code. En outre, je trouve que c'est plus idiomatique, mais c'est quelque chose que je peux facilement passer;)


@Codygray: consexpr fonctionne comme @Matteo dit: Si tous les arguments dans un Constexpr Constances sont des constantes de la compilation, l'appel sera évalué au moment de la compilation, sinon, autrement, Il est exécuté à l'exécution comme toute autre fonction.


7 Réponses :


1
votes

Je ne pense pas que vous puissiez faire cela; La seule façon dont vous pouvez le faire serait d'avoir un paramètre ConstexPR ConstexPR comme paramètre modèle pour la version de modèle de factorielle , mais consexpr Les paramètres de fonction ne sont pas admis.


0 commentaires

7
votes

ne peut pas être fait, sauf si vous avez une machine de temps.

Le paramètre à la fonction est traité au moment de l'exécution. Oui, dans votre cas C'est une constante littérale, mais c'est un cas particulier.

Dans les définitions de la fonction, les paramètres types sont fixés au moment de la compilation (et peuvent donc être utilisés pour déduire des paramètres de modèle), mais les paramètres les valeurs sont uniquement fixes à Runtime.

Pourquoi avez-vous besoin de cela? Est-ce juste pour que vous n'ayez pas à taper le <> 's?


2 commentaires

À peu près, j'ai une base de code énorme avec des appels à plusieurs fonctions que j'ai réécrit en tant que modèle. Remplacer les noms est trivial, mais tournant tout f (2, 3, "abc", vrai) dans f <2, 3, true> ("ABC") est un peu plus délicat.


Que diriez-vous d'une macro pour convertir f (2, 3, "abc", true) dans f_impl <2, 3, true> ("abc") ?



0
votes

Non, ce n'est pas possible, sauf si vous souhaitez créer un énoncé d'interrupteur énorme:

int getFactorial( const int v )
{
  switch ( v )
  {
    case 1 : return factorial<1>();
    case 2 : return factorial<2>();
    //etc
    default:
       ;
  }
  return 0;
}


0 commentaires

1
votes

Non, vous ne pouvez pas faire ça. Les arguments de modèle ne peuvent être déduits que du type de l'argument de la fonction, pas la valeur , qui ne sera pas connue en général à l'heure de la compilation.

Bien sûr, vous pouvez réécrire factorial comme non-modèle consexpr fonction; Ensuite, il serait évalué à la compilation si l'argument est connu alors.


0 commentaires

9
votes

Votre code actuel serait normalement écrit comme suit, je pense: xxx

si vous l'appelez avec une expression constante, telle que factorielle (5) , alors toute la magie du compilateur entrera en jeu. Mais si vous faites int A = 3; factorielle (a) , alors je pense que cela tombera sur une fonction conventionnelle - c'est-à-dire qu'il n'aura pas construit une table de recherche de réponses précontrictées.

En général, vous devriez marquer chaque fonction et constructeur comme consexpr si vous le pouvez. Vous ne perdez rien, le compilateur le traitera comme une fonction normale si nécessaire.


7 commentaires

Je ne savais pas que Constexpr okspr works opt-out comme ça. Malheureusement, le code n'est qu'un exemple et j'ai besoin d'une matrice de taille fixe à l'intérieur de la fonction réelle, donc j'ai besoin d'un modèle avec la taille de la matrice en tant que paramètre.


Créer peut-être une gamme de pointeurs de la fonction aux fonctions modèles à la compilation, et regardez-les au moment de l'exécution? Factorial [3] (.. Autres args ..)


@PEZCODE: Modifiez la factorielle sur une macro qui appelle le code de modèle, Aaron: vous ferez mieux de construire une gamme des résultats


@MOOINGDUCK, YEP, mais voir le commentaire de PezCode sur cette réponse - Je pense que la vraie application est plus compliquée que cela. J'ai l'impression d'avoir l'impression que certains arguments doivent être ces modèles-Ints, alors que leur peut être d'autres paramètres également.


Si vous pouvez marquer chaque fonction et tout constructeur comme consexpr sans aucune conséquence négative, cela soulève (encore) la question de savoir pourquoi ce n'est pas la valeur par défaut des compilateurs C ++ 11 ... Je suppose que c'est le Problème sacré de la compatir de retour sacré à nouveau.


Je ne suis pas expert @codygray, mais je pense que le seul inconvénient avec Parfait Constexpr pour tout est que la compilation pourrait être beaucoup plus lente ou peut-être même être bloquée dans une boucle infinie. PS: Et peut-être que vous dites des problèmes de compatibilité, certains logiciels pourraient supposer qu'ils traitent des fonctions «réelles».


Une fonction marquée comme consexpr est limitée dans ce que vous pouvez faire à l'intérieur de celui-ci pour limiter le fardeau des écrivains compilateurs pour pouvoir le calculer au moment de la compilation. Vous marquez des fonctions avec consexpr pour dire au compilateur qu'il devrait se plaindre si vous ne répondez pas à ces restrictions afin que votre code soit portable à d'autres compilateurs.



0
votes

Utilisez une macro maléfique: xxx


0 commentaires

0
votes

Une solution de contournement possible pour ce type de problème consiste à utiliser certains struct comme ceci: xxx

alors nous pouvons avoir une surcharge sur constante comme ceci: xxx

Utilisation de la valeur de x au temps de compilation et surcharges d'exécution f (int) . La partie agaçante est qu'elle nécessite une certaine discipline sur le site d'appel, car chaque constante littérale doit être enveloppée comme constante {} (avec macro ou quelque chose comme ça).


0 commentaires