2017-04-17 4 views
0

Pour être-fool preuve, il a besoin:Quelle fonctionnalité C++ assure l'extraction infaillible T & from optionnel <T>?

  • syntaxe propre
  • possibilité d'utiliser auto
  • utilisation atomique, pour éviter les erreurs accidentelles comme if (!opt) { opt->call(); }
  • aucune assertion d'exécution (EDIT : et exceptions)
  • aucun avertissement de compilateur
  • (facultatif) aucun vérificateur statique warnin gs

Jusqu'à présent, j'ai essayé ces 4 options (supposons avoir une optional<T> opt; variable):

Option 0. utilisation standard

if (opt) { 
    opt->call(); 
} 
  • + Un code propre
  • + Flux de contrôle naturel, ayant else déclaration
  • - Non atomique
  • -operator-> est exposée dans un type Nullable, il est donc facile d'appeler opt->call() sans if chèque

Option 1. Créer un pointeur intelligent almost_present<T> avec _DEBUG -uniquement le champ mutable boolean checkedPresent qui est défini sur true lorsque l'utilisateur le fait operator bool:

if (almost_present<T> nonull = opt.if_present()) { 
    // `operator->()` and `operator T&()` assert if called without doing `if (nonull)` 
    nonull->call(); 
    T& x = nonull; 
} 
  • + flux de contrôle naturel, ayant déclaration else
  • + affirmera si l'utilisateur ne valeur vérifie pas avant le référencement, même si elle est présente
  • - contrôles d'exécution
  • -almost_present<T>::operator bool() const doit modifier checkedPresent champ
  • - mai utiliser accidentellement nonull dans la branche else, mais c'est mineur

Option 2. basé Range-trick boucle de http://loungecpp.net/cpp/abusing-range-for/: optional<T> ou optional<T>::if_present() met en œuvre des méthodes begin() et end() pour ressembler à une collection de 0 ou 1 articles

for (auto& nonull : opt.if_present()) { 
    nonull.call(); 
} 
  • + syntaxe propre
  • - Inconditionnel return à l'intérieur de toute boucle produit warning C4702: unrechable code (VC2017)
  • - Aucune déclaration else, doivent appeler if (!opt) séparément, et ce n'est pas atomique
  • - On dirait une boucle, peut être mal interprété si T est une collection

Option 3. lambdas

opt.if_present([](auto& nonull) { nonull.call(); }); 
auto result = opt.map(
     [](auto& nonull) { return nonull.call(); }, 
     []() { return what_if_null(); } 
    ); 
  • + cela fonctionne
  • - pas une syntaxe propre - difficile à lire et à déboguer

Pour l'instant, j'utilise une combinaison de « pour » boucle et « lambdas »

+0

Presque présent me semble optionnel. – Yakk

+0

Je n'utiliserais pas .2 et .3 pour autre chose que du divertissement. Ce genre de code est effectivement source de confusion. – Pavel

+0

@Yakk, 'almost_present' affirme préventivement si vous avez oublié' if', donc il suffit de couvrir ce code avec 1 test. Et 'std :: optionnel ' échouera seulement quand vous passerez une valeur vide, ce qui pourrait être très rare. –

Répondre

0
auto v = opt.value(); 

jette un bad_optional_access si opt contient aucune valeur.

+0

Eh bien, c'est ce que j'essaie d'éviter - runtime affirme et jette –

+0

@MykolaBogdiuk Vous n'avez pas mentionné que vous vouliez éviter les exceptions. –

+0

Formellement oui, mais je n'utiliserais pas 'optionnel ' si je savais que ce n'est pas vide en premier lieu. Éditera la question. –