Search code examples
c++language-lawyerc++14implicit-conversionconversion-operator

Second order implicit conversion


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?


Solution

  • 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.