J'ai une méthode qui ressemble à ceci:
template <typename T> T Test<T>::FindItem(T item) { if(found) //return original value, no problem here else //I want to return NULL here, like: return NULL; }
9 Réponses :
La plupart des types sont construcables par défaut que vous avez une classe de modèle de traits qui peut être spécialisée (avec le renvoi par défaut d'un objet initialisé par défaut).
template <class T> struct Make { static T Default() { return T(); } }; class not_default_constructable { public: explicit not_default_constructable(int i) {} }; // specialize for not_default_constructable template <> struct Make <not_default_constructable> { static not_default_constructable Default() { return not_default_constructable(42); } };
ici , Stroustrup donne quelques arguments pour éviter < Code> null code> en C ++: p>
0 code>, il n'y a donc pas de gain réel [et plus à taper] li>
- C'est une macro et les macros sont mieux évités dans C ++ li>
ul>
La suggestion, à nouveau de cette page est la suivante: p>
- Utilisez une plaine
0 code> ou (pour c ++ 0xwateverver) nullptr code>. li>
ul>
Deuxièmement, si vous souhaitez renvoyer un pointeur non valide comme signal de défaillance, vous devez déclarer la fonction comme renversant un pointeur à un type, pas le type lui-même. P>
Troisièmement, la plupart des fonctions de bibliothèque standard () devront renvoyer des itérateurs, plutôt que des éléments directement. Cela vous donne la possibilité de mettre en œuvre le cas "rien trouvé" différemment. P>
Pourquoi ne pas utiliser null? Pour moi, il est plus clair que vous traitez avec des pointeurs Iso. entiers de cette façon.
L'utilisation ou non de NULL est une question de style de codage juste à côté de la position des supports curcly ou du nombre d'espaces à utiliser lors de l'indentation. J'ai utilisé les deux, je ne préfère pas l'un sur l'autre tant qu'il est utilisé de manière cohérente. Il y a des arguments à la fois, je ne pense pas que j'ai entendu parler de convaincant.
@ Kristof: Stroustrup fait un argument assez marginal contre - recherche.att.com/ ~ bs / bs_faq2.html # null
@ Kristof: J'ai ajouté que très lien avec la réponse elle-même, avant de voir que c'était déjà ici dans votre commentaire. Je vais le laisser, mais merci!
Le fait que C ++ manque de mot-clé code> null code> est une défaillance de la conception de la langue, malgré tout argument STROSTRUP. Les pointeurs sont différents des entiers, de la période et doivent donc être syntaxiquement différentes.
Eh bien, la non-existence du mot-clé NULL (à rectifier en C ++ 0x) est un symptôme du fait que les pointeurs et les entiers peuvent être convertis implicitement. Je pense que c'est un pire échouage (et les auteurs de GCC sont d'accord, car il y a un avertissement pour cela), mais il est hérité de C et de supprimer, il s'agirait probablement d'une rupture de compatibilité pour le comité C ++.
Vous dites "N'utilisez pas NULL", reliant la déclaration de STROSTRUP où il dit "en C ++, la définition de NULL est 0, donc il n'y a qu'une différence esthétique.". Semble étrange - je suis sûr que STROSTRUP ne dirait pas "N'utilisez pas NULL".
Si vous souhaitez revenir en valeur et que vous ne voulez pas gâcher avec des pointeurs de retour et de nouveau / Supprimer, vous pouvez simplement faire comme suit:
Test<int> var; boost::optional<int> V = var.FindItem(5) if (V) { // found int val = *V; } else { // not found }
Je n'utilise pas boost alors ne peut pas utiliser boost :: aucun
Si vous souhaitez renvoyer une valeur singulière pour un type qui n'en avez pas, vous devrez utiliser facultatif ou quelque chose d'équivalent. Si vous n'avez pas accès à Boost, vous pouvez toujours définir la vôtre (un autre nom commun utilisé pour cela est faillible).
Vous devez retourner t * non t p>
Peut-être que je suis trop simpliste, mais je préfère simplement retourner un bool code>:
-1 Sauf que cela ne fonctionne pas, car la fonction prend élément code> par copie.
Si vous retournez une copie de l'élément d'origine lors de sa constatation (comme indique le commentaire dans le code de l'Asker), vous pourriez aussi bien retourner un BOOL. L'appelant a déjà l'article.
Vous avez une fonction qui pourrait renvoyer un objet valide, mais également une indication qu'aucun objet valide n'existe. Combiné à une situation dans laquelle toutes les valeurs d'objet possibles sont valides, il s'agit d'un problème de conception avec votre fonction de recherche. (Même si vous avez modifié la fonction de manière à renvoyer une chaîne vide si elle n'en trouve pas une, comment cela se distinguerait-il de manière réussie de trouver une chaîne vide?) P>
Au fil du temps, plusieurs moyens de sortir de ce dilemme ont été trouvés. Vous pouvez donc retourner un pointeur / itérateur au lieu de retourner la valeur réelle. Ensuite, un Quoi qu'il en soit, avant de sauter et faites-le, vous devez vous demander pourquoi vous écrivez votre propre conteneur / algorithme au lieu d'en utiliser un de STD LIB. p> NULL code> Le pointeur / End Itérateur indiquerait "non trouvé". Ou vous pouvez prendre une valeur par référence non-Const, attribuez-lui le résultat et indiquer le succès / l'échec par un booléen retourné. Ou prenez l'une des autres solutions postées ici. Mais tous nécessiteront que vous modifiez l'interface de la fonction - car, comme il s'agit d'une erreur de conception. P>
retour t () code>. Si
t code> est de type
Détype * code>, il sera initialisé à un pointeur NULL. Si
t code> est de type
Automype code>, il retournera un objet créé avec le constructeur par défaut, qui devrait suffire (
std :: string code> sera vide , des types intégrés tels que
int code> s seront 0, etc.). p>
Cela ne fonctionne pas si 0 est une valeur de retour valide. ATOI () CODE> a le même problème.
À mon avis, vous essayez de vous compliquer un peu en essayant de retourner une valeur nulle ...
faire quelque chose de similaire à celui-ci: p> Lancer une classe vide ne coûte rien ... p> p>
Vous pouvez lancer une exception lorsqu'il n'est pas trouvé. P>
Depuis que vous n'avez aucune connaissance du type étant recherché et renvoyé, vous ne pouvez désigner aucune valeur particulière de ce type comme code d'erreur. En substance, vous essayez de serrer le domaine complet d'un type plus une valeur d'erreur dans le domaine du type. P>
Les suggestions d'utilisation d'itérateurs ou d'autres emballages aident à résoudre le problème en étendant le domaine du type de retour pour englober les valeurs d'erreur, mais si vous souhaitez vous tenir aux types réels que vous avez affaire, des exceptions sont votre meilleur choix. C'est ce qu'ils sont pour. P>
C'est une erreur de temps compilée. Pas un temps d'exécution.
Temps d'exécution pour std :: String, STD :: String (Cons-Char *) sera appelé
@Naveed: J'utilise le compilateur VC de Visual Studio 2005 et ce n'est pas une erreur de compilation de la compilation. Ne peut pas dire à propos de GCC.
Oups..solire mon erreur. Oui, il se bloque dans VS2008 également.
Initialisation d'un
std :: String Code> avec
NULL code> n'est pas une erreur de compilation, mais invoquera un comportement non défini, échoué probablement au moment de l'exécution.