Skip to content

Trivia impact: real

A Base Class That Cannot Be Converted

two type traits ask different questions about private inheritance

struct Base {};
struct Derived : private Base {};

std::cout << std::is_base_of<Base, Derived>::value << "\n";
std::cout << std::is_convertible<Derived*, Base*>::value << "\n";

Does this compile? What does it print?

Answer
1
0

Base really is a base class of Derived, but an unrelated caller cannot implicitly convert a Derived* to a Base* through its private base.

Why

[meta.rel] defines is_base_of as a hierarchy question and explicitly counts private, protected, and ambiguous bases. The same section defines is_convertible in terms of a hypothetical return expression with access checking in an unrelated context. Since this private base conversion is inaccessible there, the first trait is true and the second false.

Where it shows up

Generic code often needs to choose between “is this type in that hierarchy?” and “may this value be passed where that base is expected?” The first calls for is_base_of; the second calls for is_convertible, so the distinction has real consequences for trait-based APIs.

Takeaway: inheritance and public substitutability are related, but not the same trait.

Try it: g++ -std=c++17 main.cpp -o demo && ./demo

Open in Compiler Explorer ↗ Quiz this entry