Esiste un equivalente C++ per l'operatore di coalescenza null C#? Sto facendo troppi controlli null nel mio codice. Quindi cercavo un modo per ridurre la quantità di codice nullo.C# null operatore equivalente coalescente per C++
risposta
Non c'è un modo per fare questo per impostazione predefinita in C++, ma si potrebbe scrivere uno:
in C# il ?? operatore è definito come
a ?? b === (a != null ? a : b)
Così, il metodo C++ sarà simile
Coalesce(a, b) // put your own types in, or make a template
{
return a != null ? a : b;
}
In questo metodo, b viene valutato anche se a non è nullo. Questo potrebbe essere un problema se b ha effetti collaterali. – Amnon
@Amnon: Infatti. Considera: 'p = Coalesce (p, new int (10));'. Inoltre, sembra che in C# l'operando di destra non possa essere NULL (non può essere controllato in fase di compilazione, dato che non ci sono tipi nullable in C++?). D'altra parte: c'è così tanto bisogno in C++, quindi non puoi semplicemente digitare 'a? a: b; '? – UncleBens
E se è C++ 11 o superiore, usa 'nullptr'. Non c'è nullo in C/C++, solo 'NULL' è definito in alcune intestazioni. http://stackoverflow.com/questions/1282295/what-exactly-is-nullptr –
ne dici di questo?
#define IFNULL(a,b) ((a) == null ? (b) : (a))
attenti a IFNULL (a ++, b) Sì, mi rendo conto che vorresti comunque guardarti da ciò, se pensi che possa essere nullo. IFNULL (SomeClass.DoSomethingReallyLong(), "") causa anche problemi. – McKay
Bene, mi serve per essere pigro. L'utilizzo di un metodo di modello è sicuramente la strada da percorrere qui, poiché evita effetti collaterali e avrà prestazioni equivalenti (o migliori). Aggiungerò un +1 sulla soluzione di @ McKay ora. :-) –
Un modello di funzione non ha necessariamente prestazioni uguali o migliori. Questo "cortocircuito" ('b' non viene valutato a meno che' a' sia null), mentre gli argomenti di una funzione vengono sempre valutati. –
Ho appena trovato questo: The ?? operator aka the Null Coalescing Operator
Hai anche in C e C++ come un'estensione GNU utilizzando il “:” operator:
stringa pageTitle = getTitle() ?: "Titolo predefinito";
Utilizzo di modelli e C++ 11 lambda. Il primo argomento (lato sinistro) viene valutato solo una volta. Il secondo argomento (lato destro) viene valutato solo se il primo è falso (notare che 'if' e '?' Convertono staticamente l'espressione fornita in bool, e quei puntatori hanno 'esplicito bool operatore() const' che è equalivent a '! = nullptr')
template<typename TValue, typename TSpareEvaluator>
TValue
coalesce(TValue mainValue, TSpareEvaluator evaluateSpare) {
return mainValue ? mainValue : evaluateSpare();
}
Esempio di utilizzo
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";
sarà solo stampare '0xf' nella console. Dovendo scrivere un lambda per i RHS è un po 'di testo standard
[&]() { return <rhs>; }
ma è il meglio che si può fare se uno manca il supporto per la sintassi del linguaggio.
Questa è l'unica risposta che offre la semantica identica di un operatore a coalescenza nulla. Probabilmente raramente vale la pena, però. In realtà, questa funzione deve solo essere nella lingua. –
Voglio solo di ampliare la risposta di @Samuel Garcia generalizzando il modello e l'aggiunta di macro di supporto per ridurre il 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 (
Usando le macro, si può solo:
int* f();
int* g();
int* h();
int* x = COALESCE(f() OR_ELSE g() OR_ELSE h());
I spero che questo ti aiuti.
In GCC, è "a?: B" ma non è portabile. – MSalters