Ce nouvel article au sujet des nouveautés du C++17 traite de la nouvelle syntaxe pour les initialisations aux seins des instructions de selection (if et switch). Ces changements sont issus de la proposition P0305R1 (“Selection statements with initializer“).
Motivation
Il est fréquent d’utiliser une variable uniquement pour une instruction if (ou switch ). Un exemple classique est l’utilisation d’un objet RAII comme std::lock_guard :
1 2 3 4 5 6 7 8 9 |
{ std::lock_guard<std::mutex> lk(mtx); // Section 1. if (vec.empty()) vec.push_back(value); } // Section 2. } // Section 3. |
Il se pose alors un problème de portée. Le bloc artificiel délimité par les accolades permet d’éviter que la variable lk soit accessible en dehors du if , la rendant ainsi indisponible pour la section 3 et s’assurer que le destructeur de lk est effectivement appelé en fin de bloc.
Outre le fait que ça alourdit le code, cette technique a le défaut de ne pas complètement limiter la portée de la variable. En effet, lk est toujours accessible dans la section 2. Pire encore, la section 1 qui se situe entre l’initialisation de la variable et son utilisation est une potentielle source d’erreur, puisque la variable pourrait être altérée par inattention si du code venait à être ajouté par la suite.
Ce problème existe également avec l’instruction switch , comme le montre l’exemple suivant :
1 2 3 4 5 6 7 8 9 |
{ auto res{ return_code }; switch (res) { case ResponseCode::ERROR: // ... } // res est toujours défini. } |
Les initialiseurs dans les instructions de selections
La P0305R1 propose donc de supporter l’ajout (optionnel), d’une instruction d’initialisation pour if et switch, de façon similaire à ce que propose la boucle for :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
if(initialisation; condition) instruction1; else instruction2; // EQUIVALENT DE : { initialisation; if(condition) instruction1; else instruction2; } |
On peut donc modifier les exemples précédents pour profiter de ces initialiseurs :
1 2 3 4 5 6 7 8 9 10 |
if (std::lock_guard<std::mutex> lk{mtx}; vec.empty()) { vec.push_back(value); } switch (auto res{ return_code }; res) { case ResponseCode::Error: break; // ... } |
Vous pouvez donc constater que cet ajout simplifie le code dans le cas où une variable est crée uniquement pour une condition ou un switch . On pourrait également citer l’exemple de la recherche dans std::map :
1 2 |
if(auto it = map.find(key); it != m.end()) // Instructions. |
Cette nouvelle possibilité du langage est donc bien utile, et, même si elle ne va pas révolutionner notre façon de programmer en C++, va permettre de régler la portée des variables plus finement avec les if et switch.
Références
- P0305R1 [EN].
- if statement – cppreference.com [EN]
- switch statement – cppreference.com [EN]
You must log in to post a comment.