c++c++11base-classexplicittypecast-operator

Conversion to base class never used


I have two classes, one is privately derived from the other (because I don't want to expose the interface of the base). However later I want to create a reference to the base.

I can do it with a normal member function base() but not with a cast operator because this operator is never called

clang warns about it, because it says "it will never be called".

Why is it that cast operator is ignored and overwritten by a private element? Is this an inconsistency in the language?

Actually, I think it has a it makes public the base reference and nothing else. Even more, if it worked it could be explicit.

class A{
    int v_;
public:
    void f(){}
};

class B : A{ // A is private base because I don't want the f() interface
    int w_;
public:
    A const& base() const{return *this;}
    /*explicit*/ operator A const&() const{return *this;} // never called, warning in clang
};

int main(){
    A a = {};
    B b = {};
    A const& a2 = b.base();
    A const& a3 = b; // bad, But why?
    A const& a4{b}; // explict doesn't help
    A const& a5 = b.operator A const&(); // works in clang (but with a contradictory warning), doesn't work with gcc
}

Solution

  • In cases a3 and a4 you are initializing an reference with an lvalue. In this situation, if the referenced type is a base class of the initializer's type, the reference binds directly to the initializer, there are no conversions involved (C++17 [dcl.init.ref]/5).

    Since the base class is not accessible, the program is ill-formed (dcl.init.ref/4).

    I'm not sure about the access checking rule in a5, although it seems moot in practice as you wouldn't design code so that someone had to write that syntax.

    See also [class.conv.fct]/1:

    A conversion function is never used to convert a (possibly cv-qualified) object to the (possibly cv-qualified) same object type (or a reference to it), to a (possibly cv-qualified) base class of that type (or a reference to it), or to (possibly cv-qualified) void.