Si j'ai deux pointeurs du même type et que l'un est nul, y a-t-il une fonction / une seule ligne évidente qui peut renvoyer efficacement celle qui n'est pas nulle? Je sais que je peux le faire avec des blocs if imbriqués, mais je me demande simplement s'il existe un moyen plus compact de le faire.
Edit: Ce serait optimal si cela pouvait également renvoyer null si les deux ou aucun des deux ne sont définis.
4 Réponses :
Opérateur conditionnel:
pointer = (p1 && p2) ? nullptr : ((p1 != nullptr) ? p1 : p2);
Pour renvoyer null si les deux ne sont pas nuls:
pointer = (p1 != nullptr) ? p1 : p2;
Si les deux sont nuls, renvoyer l'un ou l'autre sera renvoie null.
Le ternaire est très bien, mais peut nécessiter un ajout à l'adresse "... return null si les deux ... sont définis." (qui peut avoir été ajouté après votre réponse)
@ DavidC.Rankin C'était, je suis désolé. Bien que j'aie complètement oublié les conditions ternaires, il ne semble pas (du moins évidemment) que je puisse les utiliser pour évaluer les 4 cas.
Bonne mise à jour, j'aime bien, mais je dois toujours y jeter un coup d'œil pour trier les doubles ternaires :) Le correctif vaut la peine.
Une comparaison explicite avec nullptr n'est pas nécessaire car std :: nullptr_t est implicitement convertible en bool : voir [conv.bool] via [conv] / 4 .
Edit: Ce serait optimal si cela pouvait également renvoyer null si les deux ou aucun n'est défini.
Si vous souhaitez renvoyer uniquement l'unique non-nullptr entre les pointeurs
aetb, vous pouvez faire quelque chose de similaire à:void *rtn_defined_unique (const void *a, const void *b) { /* if neither or both, return NULL */ if ((a == nullptr && b == nullptr) || (a && b)) return NULL; if (a != nullptr) /* if a, return a */ return a; return b; /* otherwise, it's b */ }
Dans d'autres langues, cette fonctionnalité est appelée coalesce. Comme dans sql. Apparemment, il n'y a pas de fonction intégrée mais voici une discussion des différentes approches pour l'implémenter Opérateur de fusion nul C # équivalent pour c ++
Voici une version bit à bit sans branche
void* getUniquePointer(const void *a, const void *b)
{
return (void*)((uintptr_t)a | (uintptr_t)b);
}
Clang la compilera en
test rdi, rdi
setne al
test rsi, rsi
setne cl
xor cl, al
or rsi, rdi
xor eax, eax
test cl, cl
cmovne rax, rsi
ret
lien Godbolt pour la comparaison avec d'autres solutions p>
Si vous ne avez pas besoin de null retour si les deux sont définis alors ce sera encore plus simple
void* getUniquePointer(const void * const a, const void * const b)
{
auto mask = -(uintptr_t)(!!a ^ !!b); // all ones if only one is defined, 0 otherwise
return (void*)(((uintptr_t)a | (uintptr_t)b) & mask);
}
Retour A? A: B; Code>?La compacité n'est pas particulièrement utile.
if (a == nullptr) retourne b; else return a;est susceptible de générer le même code quereturn a? a: b;. Optimisez la lisibilité. (Personnellement, je trouve que l'opérateur conditionnel est suffisamment lisible. YMMV.) Vous devriez également réfléchir à ce qu'il faut faire si les deux pointeurs sont nuls, ou si ni l'un ni l'autre ne l'est. Si vous ne souhaitez pas gérer ce cas, ce n'est pas grave, mais vous devez le documenter comme une exigence sur l'appelant.@tkausl Désolé, j'étais au milieu d'une modification lorsque vous avez publié cela.
@KeithThompson Ternary aurait été bien mais je veux gérer le cas où les deux / ni l'un ni l'autre ne sont définis.
Ne peut-on pas enchaîner les déclarations ternaires dans cpp?