CodeNebula
C++20stladvanced

std::derived_from (C++20 Addition)

C++20 · The Big Four · Compiler flag: -std=c++20

Explanation

Concept that checks if a type is publicly and unambiguously derived from a base type. Unlike `std::is_base_of`, it enforces public inheritance, preventing accidental use of privately derived types.

Real-World Scenario

Constrain a plugin registration system to accept only classes derived from a `Plugin` base class.

Quick Snippet

snippet.cpp
#include <concepts>

struct Plugin { virtual void execute() = 0; };
struct AudioPlugin : Plugin { void execute() override {} };

template<std::derived_from<Plugin> T>
void register_plugin(T& plugin) {
    plugin.execute();
}

Full Example

derived_from.cpp
// CodeNebula - C++20 Example: std::derived_from Concept
// Compile: g++ -std=c++20 -Wall -Wextra -o example derived_from.cpp

// std::derived_from<Derived, Base> checks whether Derived is publicly
// and unambiguously derived from Base, or is the same type as Base.

#include <concepts>
#include <iostream>
#include <string>

struct Animal {
    virtual std::string speak() const { return "..."; }
    virtual ~Animal() = default;
};

struct Dog : public Animal {
    std::string speak() const override { return "Woof!"; }
};

struct Cat : public Animal {
    std::string speak() const override { return "Meow!"; }
};

struct Robot {};  // Not derived from Animal

// Function constrained to accept only Animal-derived types
template <std::derived_from<Animal> T>
void make_speak(const T& creature) {
    std::cout << "The creature says: " << creature.speak() << "\n";
}

// Factory function returning any Animal subclass
template <typename T>
    requires std::derived_from<T, Animal>
T create_animal() {
    return T{};
}

int main() {
    Dog dog;
    Cat cat;

    // Use constrained function
    make_speak(dog);
    make_speak(cat);
    // make_speak(Robot{});  // Compile error: Robot not derived from Animal

    // Use factory
    auto d = create_animal<Dog>();
    std::cout << "Factory dog says: " << d.speak() << "\n";

    // Compile-time checks
    std::cout << "Dog derived from Animal: "
              << std::derived_from<Dog, Animal> << "\n";
    std::cout << "Animal derived from Animal: "
              << std::derived_from<Animal, Animal> << "\n";
    std::cout << "Robot derived from Animal: "
              << std::derived_from<Robot, Animal> << "\n";
    std::cout << "int derived from Animal: "
              << std::derived_from<int, Animal> << "\n";

    return 0;
}

// Expected output:
// The creature says: Woof!
// The creature says: Meow!
// Factory dog says: Woof!
// Dog derived from Animal: 1
// Animal derived from Animal: 1
// Robot derived from Animal: 0
// int derived from Animal: 0
Run command
g++ -std=c++20 -Wall -Wextra -o example derived_from.cpp