Le type std::any

Depuis C++ 17, un type std::any est offert pour contenir un objet de n'importe quel type, de manière non-intrusive (au sens où std::any peut même contenir un primitif). Par exemple :

#include <any>
#include <iostream>
#include <string>
using namespace std;
int main() {
   any x = 3; // x contient un int
   x = "J'aime mon prof"s; // x contient un std::string
   cout << any_cast<string>(x) << endl; // J'aime mon prof
}

Un tel type est utile pour des situations où les types sont inconnus a priori, et où la gamme des types possibles est ouverte (si l'ensemble des cas possibles est fini, alors il est probable que variant soit une meilleure option).

 Les fonctionnalités cles de ce type sont :

Fonctionnalité Rôle Exemple

Vider un any ou créer un any vide

Un any sera vide par défaut, ou si on appelle sa méthode reset()

any a;
// ...
a = 3;
// ...
a = any{}; // ou a = {};
a = "Allo"s;
// ...
a.reset();

Insérer une valeur

Il est possible d'insérer une valeur dans un any :

  • À la construction
  • Par une affectation
  • Par emplacement
  • Par fabrication, à l'aide d'une fonction make_any(), ce qui réalise en pratique une fabrication par emplacement
any a{ 3 };
any b;
// ...
b = 3;
b.emplace<string>("Coucou");
a = make_any<string>("Coucou");

Découvrir le type entreposé

Un any réalise de l'effacement de type sur la valeur entreposée, mais permet de découvrir ce type dynamiquement à l'aide de sa méthode type(), qui repose sur RTTI et retourne le typeid du type inséré.

Notez toutefois qu'il est possible d'implémenter any sans avoir recours à RTTI; si vous n'utilisez pas les mécanismes de any qui dépendent de RTTI, vous pouvez en faire l'économie.

any x = "Coucou"s;
assert(x.type() == typeid(string));

Tester pour la présence d'une valeur

Il est possible de tester un any pour la présence d'une valeur en appelant sa méthode has_value(). Il est aussi possible de réaliser ce test à l'aide de sa méthode type(), qui retournera typeid(void) si le any est vide.

any f();
// ...
if(auto x = f(); !x.has_value())
   cout << "Il est vide!" << endl;
if(auto x = f(); x.type() == typeid(void))
   cout << "Il est vide!" << endl;

Obtention de la valeur entreposée

Il est possible d'extraire le contenu d'un any par un any_cast<T>. Si le T demandé ne correspond pas au T entreposé, any_cast<T> lèvera un bad_any_cast

any x = "Coucou"s;
auto s = any_cast<string>(x); // Ok
try {
   auto n = any_cast<int>(x);
} catch (bad_any_cast&) {
   cerr << "Oups!\n";
}

Ce type peut faciliter l'écriture de certaines interfaces, et peut contribuer à certaines techniques de mise à jour automatisée de logiciels.

Lectures complémentaires

Quelques liens pour enrichir le propos.


Valid XHTML 1.0 Transitional

CSS Valide !