Take the following code:
#include <iostream>
struct Base {
char x = 'b';
};
struct Derived : Base {
operator Base() { return Base { 'a' }; }
};
int main() {
Derived derived;
auto base = static_cast<Base>(derived);
std::cout << "BASE -> " << base.x << std::endl;
}
Under both g++ and clang++, this produces:
BASE -> b
I was expecting the following:
BASE -> a
Why? Because why I read this code, I see a conversion operator inside of Derived
that returns an instance of Base
containing 'a'
.
clang++ did me the courtesy of emitting a warning:
main.cpp:9:5: warning: conversion function converting 'Derived' to its base class 'Base' will never be used
operator Base() { return Base { 'a' }; }
Researching this warning, I found that this was by design (paraphrased for clarity):
class.conv.fct
The type of the conversion function ([dcl.fct]) is “function taking no parameter returning conversion-type-id”. A conversion function is never used to convert a (possibly cv-qualified) object [...] to a (possibly cv-qualified) base class of that type (or a reference to it) [...].
So it would seem that both compilers are doing the right thing here. My question is, why does the standard require this behaviour?
If you could override the conversion-to-base-class in C++, then you could break lots and lots of stuff. For example, how exactly would you be able to get access to the actual base class instance of a class? You would need some baseof
template, similar to std::addressof
that's used to bypass the il-conceived operator&
overload.
Allowing this would create confusion as to what code means. With this rule in place, it's clear that converting a class to its base class copies the base class instance, in all cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With