C++ 11 nous a donné std::add_const
; avec C++ 17, nous avons une nouvelle structure - std::as_const()
. Le premier claque juste un const
avant le type que vous lui fournissez. La seconde est une fonction (modèle d'une) propre, et non un trait de type, qui semble faire de même - sauf lorsque le type est une référence de valeur, auquel cas elle ne peut pas être utilisée.
Je ne comprends pas très bien la motivation pour fournir std::as_const()
. Pourquoi en avons-nous besoin en plus de std::add_const
?
"Besoin" est un mot fort ... std::as_const
Existe parce qu'il est utile, pas strictement nécessaire. Puisqu'il s'agit d'une fonction plutôt que d'un trait, nous pouvons l'utiliser pour "ajouter const" aux valeurs réelles plutôt qu'à types .
Plus précisément: supposons que j'ai une variable my_value
Et que je veux la traiter comme un const
, mais pas la copier. Avant C++ 17, j'aurais besoin d'écrire:
static_cast<const MyType&>(my_value)
et si je ne veux pas spécifier explicitement le type, ce serait:
static_cast<std::add_const_t<std::remove_reference_t<decltype(my_value)>> &>(my_value)
ou si vous voulez vous salir et utiliser le casting de style C:
(const decltype(my_value) &) (my_value)
qui sont tous ennuyeux et verbeux.
Au lieu de cela, avec C++ 17, écrivez maintenant std::as_const(my_value)
et c'est tout ce qu'il y a à faire.
Remarques:
Cette fonction est désactivée pour les références rvalue même si elle fonctionne très bien pour elles. La raison est de vous aider à éviter de garder par inadvertance une référence à un passé temporaire sa destruction. Comme l'explique @NicolBolas, si vous écrivez quelque chose comme:
for(auto &x : std::as_const(returns_container())) { /* do stuff with x */ }
alors la durée de vie du conteneur retourné se termine avant la première itération de la boucle. Très facile à manquer!
Pour plus d'informations (?), Consultez la proposition officielle de cette fonction d'utilité: P007R1 , par Adam David Alan Martin et Alisdair Meredith.