C # nullo operatore coalescenza equivalente per C ++
-
21-09-2019 - |
Domanda
C'è un C ++ equivalente per l'operatore C # nullo coalescenza? Sto facendo troppi controlli nulli nel mio codice. Quindi, era alla ricerca di un modo per ridurre la quantità di codice nullo.
Soluzione
Non è 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)
Quindi, il metodo C ++ sarà simile
Coalesce(a, b) // put your own types in, or make a template
{
return a != null ? a : b;
}
Altri suggerimenti
Ho appena trovato questo: Il ?? operatore alias il Null coalescenza Operatore
Hai anche in C / C ++ come un'estensione GNU utilizzando il
?:
operatore:string pageTitle = getTitle() ?: "Default Title";
Utilizzo dei modelli e C ++ 11 lambda. Il primo argomento (lato sinistro) viene valutato solo una volta. Il secondo argomento (lato destro) viene valutata solo se il primo è falso (si noti che 'se' e '?' Cast staticamente l'espressione fornita al bool, e che i puntatori hanno 'esplicito bool operator () 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à basta stampare '0xf' nella console. Dovendo scrivere un lambda per i RHS è un po 'di boilerplate
[&] () { return <rhs>; }
ma è il meglio che si può fare se uno manca il supporto per la sintassi del linguaggio.
Che ne dici di questo?
#define IFNULL(a,b) ((a) == null ? (b) : (a))
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 (
Utilizzando le macro, si può semplicemente:
int* f();
int* g();
int* h();
int* x = COALESCE( f() OR_ELSE g() OR_ELSE h() );
Spero che questo aiuta.
C'è un'estensione GNU GCC che permette di utilizzare all'operatore ?:
con operando metà mancante, vedi condizionali con Omesso Operandi .
L'operando medio in un'espressione condizionale può essere omessa. poi, se il primo operando è diverso da zero, il suo valore è il valore della espressione condizionale.
Di conseguenza, l'espressione
x ? : y
ha il valore di
x
se questo è diverso da zero; altrimenti, il valore diy
.Questo esempio è perfettamente equivalente a
x ? x : y
In questo semplice caso, la possibilità di omettere l'operando mezzo non è particolarmente utile. Quando diventa utile è quando il primo operando fa, oppure può (se si tratta di un argomento macro), contengono un lato effetto. Quindi ripetendo l'operando in mezzo effettuerebbe il effetto collaterale due volte. Tralasciando l'operando mezzo già utilizza il valore calcolato senza gli effetti indesiderati della recomputing esso.
Questa estensione è anche supportato da clang . Tuttavia, si dovrebbe verificare con il compilatore che si sta utilizzando e le esigenze di portabilità per il codice prima di utilizzare l'estensione. In particolare, MSVC C ++ compilatori non supportano operandi omesse ?:
.
Si veda anche legati discussione StackOverflow qui .