J'ai remarqué aujourd'hui que boost::optional::is_initialized()
est marqué comme obsolète dans le référence Boost 1.64. . Mes projets sont généreusement saupoudrés de is_initialized()
pour vérifier si le boost::optional
Contient une valeur.
Je ne vois pas d'autre moyen de tester correctement si un boost::optional
Est initialisé, est-ce que je manque quelque chose?
Le boost::optional
A une explicit operator bool()
, ce qui signifie que je peux faire if(foo){...}
si foo
est un boost::optional
. Cependant, cela donnerait des résultats erronés si foo
est un boost::optional<bool>
Ou un autre boost::optional<T>
Où T
est convertible en bool
.
Qu'est-ce que Boost attend des utilisateurs?
Cependant, cela donnerait de mauvais résultats si foo est un boost :: optional ou un autre boost :: optional où T est convertible en bool.
Non, car il n'y a pas de conversion implicite vers le type sous-jacent. La "véracité" ¹ d'une option toujours fait toujours référence à son état initialisé.
La seule fois où vous avez eu l'impression que des conversions implicites se produisent est dans les opérateurs relationnels. Cependant, cela ne fait pas de conversion implicite vers le type sous-jacent, mais plutôt le levage des opérateurs, explicitement.
¹ j'entends par là une conversion booléenne contextuelle (explicite)
En effet pour boost::optional<bool>
il y a la mise en garde en mode pré-c ++ 11 :
Deuxièmement, bien que l'option <> fournisse une conversion contextuelle en bool en C++ 11, cela revient à une conversion implicite sur les anciens compilateurs
Dans ce cas, il est clairement préférable de comparer explicitement à boost::none
.
À ce jour, Boost 1.72 supporte une méthode "has_value", qui n'est pas déconseillée.
Sous le capot, il appelle juste "is_initialized". Voir le code :
bool has_value() const BOOST_NOEXCEPT { return this->is_initialized() ; }
Cela mis à part, un autre truc pratique que j'ai vu est l'idiome !!
. Par exemple:
boost::optional<Foo> x = ...
MY_ASSERT(!!x, "x must be set");
C'est essentiellement la même chose que d'écrire (bool)x
Ou la static_cast<bool>(x)
encore plus verbeuse.
En plus: il est un peu étrange que is_initialized
Soit obsolète, puis une fonction exactement équivalente avec un nom différent a été ajoutée plus tard. Je soupçonne que c'était pour la compatibilité avec C++ 17 std :: facultatif .
Pour les références futures, comme indiqué sur la documentation boost , vous pouvez comparer comme ceci à partir de maintenant:
boost::optional<int> oN = boost::none;
boost::optional<int> o0 = 0;
boost::optional<int> o1 = 1;
assert(oN != o0);
assert(o1 != oN);
assert(o0 != o1);
assert(oN == oN);
assert(o0 == o0);
Vous pourriez même faire:
if(oN != 2){}
ou simplement pour vérifier si la valeur est définie:
if(oN){}