Reputation: 11000
#include <optional>
bool f() {
std::optional<int> opt;
return opt;
}
Does not compile: 'return': cannot convert from 'std::optional<int>' to 'bool'
Consulting reference I would have thought to find an explanation, but I read it as it should be ok.
Implicit conversions are performed whenever an expression of some type T1 is used in context that does not accept that type, but accepts some other type T2; in particular:
- when the expression is used as the argument when calling a function that is declared with T2 as parameter;
- when the expression is used as an operand with an operator that expects T2;
- when initializing a new object of type T2, including return statement in a function returning T2;
- when the expression is used in a switch statement (T2 is integral type);
- when the expression is used in an if statement or a loop (T2 is bool).
Upvotes: 27
Views: 4317
Reputation: 21
This isn't really about implicit conversion, this is about the type of initialization.
What optional has is an explicit conversion function, i.e.
explicit operator bool() const;
From N4849 [class.conv.fct]/p2
A conversion function may be explicit (9.2.2), in which case it is only considered as a user-defined conversion for direct-initialization.
The above means that these cases will use the conversion function : [dcl.init]/p16
The initialization that occurs (16.1) — for an initializer that is a parenthesized expression-list or a braced-init-list, (16.2) — for a new-initializer (7.6.2.7), (16.3) — in a static_cast expression (7.6.1.8), (16.4) — in a functional notation type conversion (7.6.1.3), and (16.5) — in the braced-init-list form of a condition is called direct-initialization.
However, these cases will not use the conversion function : [dcl.init]/p15
The initialization that occurs in the = form of a brace-or-equal-initializer or condition (8.5), as well as in argument passing, function return, throwing an exception (14.2), handling an exception (14.4), and member initialization (9.4.1), is called copy-initialization.
The example in the question falls under the copy initialization case and does not use optional's conversion function.
Upvotes: 2
Reputation: 12273
From C++ docs:
When an object of type optional< T > is contextually converted to bool, the conversion returns true if the object contains a value and false if it does not contain a value.
Read about contextual conversions here:
In the following contexts, the type bool is expected and the implicit conversion is performed if the declaration bool t(e); is well-formed (that is, an explicit conversion function such as explicit T::operator bool() const; is considered). Such expression e is said to be contextually converted to bool.
- the controlling expression of if, while, for;
- the operands of the built-in logical operators !, && and ||;
- the first operand of the conditional operator ?:;
- the predicate in a static_assert declaration;
- the expression in a noexcept specifier;
- the expression in an explicit specifier;
You can do the following hack:
bool f() {
std::optional<int> opt;
return opt || false;
}
because contextual conversion happens in case of the built-in logical operators, but contextual conversion does not include return
statements and std::optional
by itself does not have implicit conversion to bool
.
Therefore, it would be the best to use the std::optional<T>::has_value
:
bool f() {
std::optional<int> opt;
return opt.has_value();
}
Upvotes: 5
Reputation: 1529
That's because implicit coversion of std::optional to bool is not supported: https://en.cppreference.com/w/cpp/utility/optional/operator_bool
constexpr explicit operator bool() const noexcept;
You have to explicitly convert to bool as bool(opt)
or simply use opt.has_value()
instead.
Upvotes: 1
Reputation: 41503
std::optional
doesn't have any facility for implicitly converting to bool
. (Allowing implicit conversions to bool
is generally considered a bad idea, since bool
is an integral type so something like int i = opt
would compile and do completely the wrong thing.)
std::optional
does have a "contextual conversion" to bool, the definition of which looks similar to a cast operator: explicit operator bool()
. This cannot be used for implicit conversions; it only applies in certain specific situations where the expected "context" is a boolean one, like the condition of an if-statement.
What you want is opt.has_value()
.
Upvotes: 27