Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is boost::optional::is_initialized() deprecated?

I noticed today that boost::optional::is_initialized() is marked as deprecated in the Boost 1.64.0 reference. My projects are liberally sprinkled with is_initialized() to check if the boost::optional contains a value.

I don't see any other way to properly test if a boost::optional is initialized, am I missing something?

The boost::optional has a explicit operator bool(), meaning that I can do if(foo){...} if foo is a boost::optional. However, this would give wrong results if foo is a boost::optional<bool> or some other boost::optional<T> where T is convertible to bool.

What does Boost expect users to do?

like image 287
Bernard Avatar asked May 23 '17 06:05

Bernard


People also ask

What is boost :: optional?

Boost C++ Libraries Class template optional is a wrapper for representing 'optional' (or 'nullable') objects who may not (yet) contain a valid value. Optional objects offer full value semantics; they are good for passing by value and usage inside STL containers.

How do you know if boost is optional?

With is_initialized() you can check whether an object of type boost::optional is not empty. Boost. Optional speaks about initialized and uninitialized objects – hence, the name of the member function is_initialized() .

What is boost none?

The expression boost::none denotes an instance of boost::none_t that can be used as the parameter. Example: #include <boost/none.hpp> optional<int> n(boost::none) ; assert ( ! n ) ; optional<T (not a ref)>::optional( T const& v ) Effect: Directly-Constructs an optional.


2 Answers

However, this would give wrong results if foo is a boost::optional or some other boost::optional where T is convertible to bool.

No, because there is no implicit conversion to the underlying type. The "truthiness"¹ of an optional always refers to its initialized state.

The only time you may have gotten the impression that implicit conversions happen is in relational operators. However, that's not doing implicit conversion to the underlying type, instead does lifting of the operators, explicitly.

¹ by which I mean contextual (explicit) boolean conversion

Update

Indeed for boost::optional<bool> there's the caveat in pre-c++11 mode:

Second, although optional<> provides a contextual conversion to bool in C++11, this falls back to an implicit conversion on older compilers

In that case it is clearly better to explicitly compare to boost::none.

like image 160
sehe Avatar answered Oct 20 '22 08:10

sehe


As of this writing, Boost 1.72 supports a "has_value" method, which is not deprecated.

Under the hood, it just calls "is_initialized" though. See the code:

bool has_value() const BOOST_NOEXCEPT { return this->is_initialized() ; }

That aside, another convenient trick I've seen is the !! idiom. Eg:

boost::optional<Foo> x = ...
MY_ASSERT(!!x, "x must be set");

It's essentially the same as writing (bool)x or the even more prohibitively verbose static_cast<bool>(x).

Aside: it is a bit odd that is_initialized was deprecated, then an exactly equivalent function with a different name got added later. I suspect it was for compatibility with C++17's std::optional.

like image 40
jwd Avatar answered Oct 20 '22 07:10

jwd