Existe-t-il un équivalent C++ pour un opérateur de coalescence C# nul? Je fais trop de vérifications nuls dans mon code. Alors cherchait un moyen de réduire la quantité de code nul.Opérateur de coalescence C# nul équivalent pour C++
Répondre
Il n'y a pas moyen de le faire par défaut dans C++, mais vous pouvez écrire un:
en C# l'?? l'opérateur est défini comme
a ?? b === (a != null ? a : b)
Ainsi, la méthode C++ ressemblerait
Coalesce(a, b) // put your own types in, or make a template
{
return a != null ? a : b;
}
Dans cette méthode b est évalué même si a n'est pas nul. Cela pourrait poser un problème si b a des effets secondaires. – Amnon
@Amnon: En effet. Considérons: 'p = Coalesce (p, new int (10));'. Aussi, il semble que dans C# l'opérande de droite ne peut pas être NULL (ne peut pas être vérifié au moment de la compilation, car il n'y a pas de types NULL dans C++?). D'un autre côté: y a-t-il tellement besoin de C++, de sorte que vous ne pouvez pas simplement taper 'a? a: b; '? – UncleBens
Et si c'est C++ 11 ou supérieur, utilisez 'nullptr'. Il n'y a pas de "null" en C/C++ de toute façon, seul 'NULL' est défini dans certains en-têtes. http://stackoverflow.com/questions/1282295/what-exactly-is-nullptr –
Comment cela?
#define IFNULL(a,b) ((a) == null ? (b) : (a))
méfiez-vous de IFNULL (a ++, b) Ouais, je me rends compte que vous voudriez vous en méfier de toute façon si vous pensez qu'un peut être nul. IFNULL (SomeClass.DoSomethingReallyLong(), "") provoque également des problèmes. – McKay
Bon point-- me sert juste pour être paresseux. L'utilisation d'une méthode de gabarit est définitivement la façon de procéder, car elle évite les effets secondaires et aura des performances équivalentes (ou mieux). Je vais ajouter un +1 sur la solution @ McKay maintenant. :-) –
Un modèle de fonction n'a pas nécessairement des performances égales ou supérieures. Ce "court-circuit" ('b' n'est évalué que si' a' est nul), alors que les arguments d'une fonction sont toujours évalués. –
Je viens de découvrir ceci: The ?? operator aka the Null Coalescing Operator
Vous avez également en C et C++ comme une extension GNU en utilisant le « : » opérateur:
chaînepageTitle = getTitle() ?: "Titre par défaut";
Utilisation de modèles et de lambdas C++ 11. Le premier argument (côté gauche) n'est évalué qu'une seule fois. Le deuxième argument (côté droit) n'est évalué que si le premier est faux (notez que 'if' et '?' Transtypent statiquement l'expression fournie en booléen, et que les pointeurs ont 'explicite operator bool() const' qui est equalivent à '! = nullptr')
template<typename TValue, typename TSpareEvaluator>
TValue
coalesce(TValue mainValue, TSpareEvaluator evaluateSpare) {
return mainValue ? mainValue : evaluateSpare();
}
Exemple d'utilisation
void * const nonZeroPtr = reinterpret_cast<void *>(0xF);
void * const otherNonZeroPtr = reinterpret_cast<void *>(0xA);
std::cout << coalesce(nonZeroPtr, [&]() { std::cout << "Never called"; return otherNonZeroPtr; }) << "\n";
me contenterai d'imprimer '0xf' dans la console. Le fait de devoir écrire un lambda pour les rhs est un peu de passe-partout
[&]() { return <rhs>; }
mais il est le meilleur que l'on peut faire si l'on manque de soutien par la syntaxe du langage.
C'est la seule réponse qui offre la même sémantique d'un opérateur de coalescence nul. Cependant, cela en vaut rarement la peine. Vraiment, cette fonctionnalité doit juste être dans la langue. –
Je veux juste élargir la réponse de @Samuel Garcia en généralisant le modèle et en ajoutant des macros d'aide pour réduire lambda boilerplate:
#include <utility>
namespace coalesce_impl
{
template<typename LHS, typename RHS>
auto coalesce(LHS lhs, RHS rhs) ->
typename std::remove_reference<decltype(lhs())>::type&&
{
auto&& initialValue = lhs();
if (initialValue)
return std::move(initialValue);
else
return std::move(rhs());
}
template<typename LHS, typename RHS, typename ...RHSs>
auto coalesce(LHS lhs, RHS rhs, RHSs ...rhss) ->
typename std::remove_reference<decltype(lhs())>::type&&
{
auto&& initialValue = lhs();
if (initialValue)
return std::move(initialValue);
else
return std::move(coalesce(rhs, rhss...));
}
}
#define COALESCE(x) (::coalesce_impl::coalesce([&](){ return (x); }))
#define OR_ELSE ); }, [&](){ return (
Utilisation des macros, vous pouvez juste:
int* f();
int* g();
int* h();
int* x = COALESCE(f() OR_ELSE g() OR_ELSE h());
I J'espère que cela t'aides.
Dans GCC, c'est 'a?: B' mais c'est non portable. – MSalters