1

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?

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
Vincent
  • 57,703
  • 61
  • 205
  • 388
  • I know you are writing a proposal for bit-iterators, for reference, see [this Q&A](http://stackoverflow.com/q/14061694/819272) on what the limitations are for such proxy classes. – TemplateRex Jan 17 '16 at 12:32

2 Answers2

3

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.

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • I seem to recall that the standardized implementation of old `std::auto_ptr` somehow managed to halfway get around this limit. Sort of. – Cheers and hth. - Alf Jan 17 '16 at 12:28
  • No, `std:auto_ptr` didn't have implicit conversion to raw pointer. It just went through an apparent double conversion in order to transfer ownership from an initializer to the declared variable. It had (has, but deprecated) a templated implicit conversion to `auto_ptr_ref`, plus a constructor providing implicit conversion from `auto_ptr_ref`. And that sequence sure *looks* like a double conversion. – Cheers and hth. - Alf Jan 17 '16 at 13:04
  • No, I was not thinking of a double conversion sequence, and I was not thinking of `operator->`. In response to your first bafflement I looked it up, and then posted the details, which you now responded to. You could read it before responding, you know. – Cheers and hth. - Alf Jan 17 '16 at 13:55
  • I think you should do it yourself. I'm allowing for Sunday-effect and all. – Cheers and hth. - Alf Jan 17 '16 at 14:04
  • TemplateRex: At the age of 50+ I still don't know how to discuss things with people who just don't get the simplest things. Who stubbornly persist in their own nonsense beliefs no matter how many times contradicted. So, I'm out of here. You could have learned something. You didn't. – Cheers and hth. - Alf Jan 17 '16 at 14:06
  • @Cheersandhth.-Alf http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#84 – TemplateRex Jan 17 '16 at 14:07
  • TemplateRex: that's **dumb**. – Cheers and hth. - Alf Jan 17 '16 at 14:07
  • @Cheersandhth.-Alf it appears there once was indeed such a loophole. tnx for insisting :) – TemplateRex Jan 17 '16 at 14:08
1

You'll need to add an operator bool to second. The compiler will only look at one user-defined implicit conversion.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56