C ++ 20 a introduit explicit (bool) qui sélectionne conditionnellement au moment de la compilation si un constructeur est rendu explicite ou non.
Voici un exemple que j'ai trouvé ici .
struct foo {
// Specify non-integral types (strings, floats, etc.) require explicit construction.
template <typename T>
explicit(!std::is_integral_v<T>) foo(T) {}
};
foo a = 123; // OK
foo b = "123"; // ERROR: explicit constructor is not a candidate (explicit specifier evaluates to true)
foo c {"123"}; // OK
Quelqu'un peut-il me dire toute autre utilité explicit (bool)
autre que l'utilisation std::is_integral
?
tuple
cette fonctionnalité.Réponses:
La motivation elle-même peut être vue dans le document .
Il est nécessaire de rendre les constructeurs explicites conditionnellement. Autrement dit, vous voulez:
Le premier est très bien, ces constructeurs sont implicites. Mais ce dernier serait mauvais, ces constructeurs le sont
explicit
. Avec C ++ 17 (ou C ++ 20 avec des concepts), la seule façon de faire ce travail est d'écrire deux constructeurs - unexplicit
et pas un:Celles-ci sont presque entièrement dupliquées - et les définitions de ces constructeurs seraient identiques.
Avec
explicit(bool)
, vous pouvez simplement écrire un seul constructeur - avec la partie conditionnellement explicite de la construction localisée juste auexplicit
-spécifiant:Cela correspond mieux à l'intention, est beaucoup moins de code à écrire et demande moins de travail au compilateur pendant la résolution de surcharge (car il y a moins de constructeurs à choisir).
la source
enable_if_t
pièce en une contrainte plus jolie et plus simple, en utilisant éventuellement des concepts. Mais c'est à côté de l'objet de cette question.Une autre utilisation possible que je vois est avec un modèle variadic:
Il est généralement bon, par défaut, d'avoir
explicit
pour constructeur avec un seul argument (sauf si la conversion est souhaitée).donc
la source
Je pourrais voir un cas d'utilisation pour exiger
explicit
conditionnellement lorsque l'entrée peut être un type de vue (pointeur brut,std::string_view
) que le nouvel objet conservera après l'appel (copier uniquement la vue, pas ce à quoi elle se réfère, rester dépendant de la durée de vie de l'objet visualisé), ou il peut s'agir d'un type de valeur (prend possession d'une copie, sans dépendances de durée de vie externes).Dans une situation comme celle-ci, l'appelant est responsable de maintenir vivant l'objet visualisé (l'appelé possède une vue, pas l'objet d'origine), et la conversion ne doit pas être effectuée implicitement, car cela rend trop facile la création implicite de l'objet survivre à l'objet qu'il voit. En revanche, pour les types de valeur, le nouvel objet recevra sa propre copie, donc bien que la copie puisse être coûteuse, elle ne rendra pas le code incorrect si une conversion implicite se produit.
la source