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
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