Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the C++ standard require compilers to ignore calls to convertion operators for base types?

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?

like image 921
OMGtechy Avatar asked Dec 08 '22 19:12

OMGtechy


1 Answers

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.

like image 155
Nicol Bolas Avatar answered Jan 21 '23 17:01

Nicol Bolas