Conversion of boost::optional to bool
Asked Answered
I

3

15

How I can prevent the last line of this code from compiling?

#include <boost/optional.hpp>

int main()
{
    typedef boost::optional<int> int_opt;
    int_opt opt = 0;
    bool x = opt;  // <- I do not want this to compile
}

The last line doesn't examine opt's contained int value, but instead compiles as a type conversion to bool, and doesn't seem to be what the user intended.

The safe bool idiom seems to be relevant here?

Intracellular answered 7/2, 2011 at 15:57 Comment(2)
What do you mean something like? Describe in English what you want. The code obviously does not describe what you want. So how should we know?Archil
you can't, boost::optional implements operator! and this is why the last line above compiles. You can't even derive from this to hide that operator - you need to fix your code.Capps
C
19

The whole point of boost::optional is to enable code like this:

void func(boost::optional<int> optionalArg)
{
    if (optionalArg) {
       doSomething(*optionalArg);
    }
}

So the implicit conversion to bool is a feature, and should not be prevented from compiling.

Corso answered 7/2, 2011 at 16:11 Comment(4)
This is not what safe bool idiom tries to solve? (artima.com/cppsource/safebool.html)Intracellular
@dimba: Naturally safe bool idiom doesn't prevent using the value in purely boolean contexts.Chercherbourg
@Chercherbourg - indeed, changing x type in last line from bool to int causes to compilation error.Intracellular
I'm not sure this answer is correct. implicit conversion to bool does indeed fail to build. But conversion to bool in boolean contexts, works. I don't know if that means that boolean contexts means the compiler considers them explicit. But proof as @Andrzej said wandbox.org/permlink/d5gAYFx3iEK8uaxyVanda
T
4

The problem that you describe used to be the case for the older versions of Boost. Ever since 1.56 release boost::optional has an explicit conversion to bool and the code that you show does not compile anymore (exactly the way you wanted). See here.

Th answered 18/11, 2016 at 14:55 Comment(1)
The "See here" link appears to be dead.Escalante
M
1

If you're using optional then you need to be able to determine if it's set before using it. The way this is implemented is with the (effectively bool) conversion.

It doesn't in my mind follow that the user didn't want what's actually written there: They should know that it's an optional and that they're checking it for validity.

Since the conversion is a built in part of boost::optional I'm not aware of any way to directly remove it.

You could of course implement a wrapper class for your particular int need that provides just the parts of the optional interface that you want, possibly with an explicit function that checks validity.

Alternately you could always use template<class T> inline T const* get_pointer ( optional<T> const& opt ) ; or its non-const version when working with optionals to make it explicit what's happening.

Microvolt answered 7/2, 2011 at 16:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.