Consider the following code:
#include <iostream>
class first
{
public:
constexpr first(bool val) noexcept : _value{val} {}
constexpr operator bool() const noexcept {return _value;}
private:
bool _value;
};
class second
{
public:
constexpr second(first val) noexcept : _value{val} {}
constexpr operator first() const noexcept {return _value;}
private:
first _value;
};
int main(int argc, char** argv)
{
first f{false};
second s{true};
bool b1 = f;
bool b2 = s; // Not compiling
return 0;
}
Until recently, I was thinking that the standard and compilers were "clever" enough to find the required conversion sequence when it exists.
In other words, I was thinking that bool b2 = s
would convert s
to first
, and then to bool
. But apparently it is not happening.
What is the correct approach to obtain an equivalent behaviour for first
and second
?
This is not possible because only a single user-defined conversion is allowed:
4 Standard conversions [conv]
7 [ Note: For class types, user-defined conversions are considered as well; see 12.3. In general, an implicit conversion sequence (13.3.3.1) consists of a standard conversion sequence followed by a user-defined conversion followed by another standard conversion sequence. — end note ]
as well as
12.3 Conversions [class.conv]
4 At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.
See also Items 5 (Be wary of user-defined conversion functions), 28 (smart pointers) and 30 (proxy classes) of More Effective C++.
For standard conversions (using builtin types), there is no restriction on how many conversions there can be in the sequence.