2009-11-23 12 views

Répondre

12

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; 
} 
+12

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

+3

@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

+1

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 –

2

Comment cela?

#define IFNULL(a,b) ((a) == null ? (b) : (a)) 
+2

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

+0

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. :-) –

+3

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. –

1

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.

+0

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. –

1

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.