27

I have a class Base defining an explicit operator bool:

struct Base {
    virtual explicit operator bool() const {
        return true;
    }
};

And I have a subclass Derived, defining an operator bool:

struct Derived : Base {
    operator bool() const override {
        return false;
    }
};

As you can observe, Derived::operator bool is explicitly not marked explicit, but marked override, so I expected the compiler to complain. However, both gcc and clang seem to agree that this is valid. Was my expectation unreasonable?

Moreover, if I use the classes as follows, TakesBool(base) does not compile (as expected), but TakesBool(derived) does:

void TakesBool(bool b) {}

int main() {
    //Base base;     TakesBool(base); // compilation error (as expected)
    Derived derived; TakesBool(derived);
    return 0;
}

This seems to indicate that Derived has an (non-explicit) operator bool, which, however, is marked override without a virtual declaration. How is this possible?

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
phimuemue
  • 34,669
  • 9
  • 84
  • 115
  • 2
    Regarding not needing `virtual` in the derived class, if a base-class has been marked `virtual` it's implicitly implied for all derived classes as well. The `override` keyword is more of a hint for the compiler, so you don't attempt to override a function using a different signature (like declaring a function in a derived class that takes different arguments than the function in the base class). So those keywords are irrelevant to the question. – Some programmer dude Aug 10 '16 at 13:39
  • 1
    Virtual dispatch still takes place. `Base* pbase = &derived; TakesBool((bool)*pbase);` will call `Derived::operator bool`. I guess `explicit` isn't considered part of the function's signature, so you're allowed to override an `explicit` conversion with a non-`explicit` one. I'm not sure if this behavior is correct though. – Miles Budnek Aug 10 '16 at 13:44
  • This is like having a `protected: virtual` function in the base class with a `public: override` in the derived class. Not a problem whatsoever. – Ben Voigt Aug 10 '16 at 14:42

1 Answers1

20

You might think that the non-explicit operator bool in Derived doesn't override explicit operator bool in Base, no, it does. The explicit specifier doesn't matter, it's not a part of function signature.

From the standard, §10.3/2 Virtual functions [class.virtual]:

(emphasis mine)

If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list ([dcl.fct]), cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.

So the compiler will complain only when the name, parameter-type-list, cv-qualification or ref-qualifier of the function doesn't match, the explicit specifier won't be considered.


You said "marked override without a virtual declaration", note that the virtual declaration for member function in derived class is superfluous, it's also virtual.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 2
    I investigated that it is possible to have a base class that has both an `explicit operator bool` and an `operator bool`, and those two are treated differently. Do you know what happens if the derived class defines `operator bool() override`? Does it override both `operator bool`s? – phimuemue Aug 10 '16 at 14:07
  • @phimuemue Why not just try it? – underscore_d Aug 10 '16 at 14:18
  • @underscore_d Yes, but I am primarily interested in an answer based on the standard. – phimuemue Aug 10 '16 at 14:19
  • 1
    @phimuemue I don't think [it](http://coliru.stacked-crooked.com/a/c21d1b23eb343109)'s possible. You can't have both `explicit operator bool` and `operator bool`. Overloading? – songyuanyao Aug 10 '16 at 14:21
  • 2
    @phimuemue It's right there: `explicit` is not part of the signature. You cannot declare 2 functions w/ same signature regardless of place in the hierarchy. Trying it would've shown you this! songyuanyao showed the same thing for Clang, and here's GCC: http://coliru.stacked-crooked.com/a/f329d16b4b8ac66b `main.cpp:9:22: error: 'virtual Base::operator bool() const' cannot be overloaded explicit virtual operator bool() const ^~~~~~~~ main.cpp:4:13: error: with 'virtual Base::operator bool() const' virtual operator bool() const ^~~~~~~~` – underscore_d Aug 10 '16 at 14:23
  • @songyuanyao You are right, I can't have both. (Sorry, I misread my code. One was const, the other not.) – phimuemue Aug 10 '16 at 14:41
  • @phimuemue Yes, const or non-const is a part of the signature for member function. So you can override the const one or non-const one in derived class. Anyway, explicit or not doen't matter. – songyuanyao Aug 10 '16 at 14:45