CodeNebula
C++20stladvanced

std::destructible (C++20 Addition)

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

Explanation

Concept that checks if a type can be destroyed (its destructor is noexcept and callable). A foundational concept required by most other object concepts.

Real-World Scenario

Constrain an object pool to only manage types that can be safely destroyed during cleanup.

Quick Snippet

snippet.cpp
#include <concepts>

template<std::destructible T>
class ObjectPool {
    std::vector<T> pool;
public:
    void clear() { pool.clear(); }  // safe: T is guaranteed destructible
};

Full Example

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

// std::destructible<T> is satisfied when T has a non-throwing destructor.
// Most types are destructible; reference types and void are not, nor are
// types with deleted or throwing noexcept(false) destructors.

#include <concepts>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

// A type with a custom destructor that logs
struct Tracked {
    int id;
    Tracked(int i) : id(i) {
        std::cout << "  Tracked(" << id << ") constructed\n";
    }
    ~Tracked() {
        std::cout << "  Tracked(" << id << ") destroyed\n";
    }
};

// A type with a deleted destructor (not destructible)
struct Immortal {
    ~Immortal() = delete;
};

// Factory that only creates destructible types
template <std::destructible T, typename... Args>
std::unique_ptr<T> safe_create(Args&&... args) {
    return std::make_unique<T>(std::forward<Args>(args)...);
}

// Check destructibility
template <typename T>
void check_destructible(const char* name) {
    std::cout << name << " is destructible: " << std::destructible<T> << "\n";
}

int main() {
    // Create tracked objects via factory
    std::cout << "Creating tracked objects:\n";
    {
        auto t1 = safe_create<Tracked>(1);
        auto t2 = safe_create<Tracked>(2);
        std::cout << "  Leaving scope...\n";
    }
    std::cout << "  Objects destroyed\n";

    // Create standard types
    auto str = safe_create<std::string>("hello");
    std::cout << "\nCreated string: " << *str << "\n";

    // Destructibility checks
    std::cout << "\nDestructibility checks:\n";
    check_destructible<int>("int");
    check_destructible<std::string>("string");
    check_destructible<std::vector<int>>("vector<int>");
    check_destructible<Tracked>("Tracked");
    check_destructible<Immortal>("Immortal");
    check_destructible<void>("void");

    // safe_create<Immortal>();  // Compile error: not destructible

    return 0;
}

// Expected output:
// Creating tracked objects:
//   Tracked(1) constructed
//   Tracked(2) constructed
//   Leaving scope...
//   Tracked(2) destroyed
//   Tracked(1) destroyed
//   Objects destroyed
//
// Created string: hello
//
// Destructibility checks:
// int is destructible: 1
// string is destructible: 1
// vector<int> is destructible: 1
// Tracked is destructible: 1
// Immortal is destructible: 0
// void is destructible: 0
Run command
g++ -std=c++20 -Wall -Wextra -o example destructible.cpp