CodeNebula
C++20stladvanced

std::swappable (C++20 Addition)

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

Explanation

Concept that checks if a type (or pair of types with `swappable_with`) can be swapped using `std::ranges::swap`. Accounts for both member swap and ADL-found swap overloads.

Real-World Scenario

Implement a generic sorting algorithm that requires its elements to be swappable.

Quick Snippet

snippet.cpp
#include <concepts>

template<std::swappable T>
void bubble_sort(std::vector<T>& vec) {
    for (std::size_t i = 0; i < vec.size(); ++i)
        for (std::size_t j = i + 1; j < vec.size(); ++j)
            if (vec[j] < vec[i])
                std::ranges::swap(vec[i], vec[j]);
}

Full Example

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

// std::swappable<T> checks that lvalues of type T can be swapped.
// std::swappable_with<T, U> checks that values of types T and U
// can be swapped with each other.

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

// Generic swap-and-report function
template <std::swappable T>
void swap_and_show(T& a, T& b) {
    std::cout << "  Before: a=" << a << ", b=" << b << "\n";
    std::ranges::swap(a, b);
    std::cout << "  After:  a=" << a << ", b=" << b << "\n";
}

// Sort two elements using swap
template <std::swappable T>
void sort_pair(T& a, T& b) {
    if (b < a) {
        std::ranges::swap(a, b);
    }
    std::cout << "  Sorted: " << a << ", " << b << "\n";
}

// Custom non-swappable type (deleted swap)
struct NoSwap {
    int value;
    NoSwap(int v) : value(v) {}
    NoSwap(const NoSwap&) = delete;
    NoSwap& operator=(const NoSwap&) = delete;
};

int main() {
    // Swap integers
    std::cout << "Swapping ints:\n";
    int x = 10, y = 20;
    swap_and_show(x, y);

    // Swap strings
    std::cout << "Swapping strings:\n";
    std::string s1 = "hello", s2 = "world";
    swap_and_show(s1, s2);

    // Swap doubles
    std::cout << "Swapping doubles:\n";
    double d1 = 1.5, d2 = 9.9;
    swap_and_show(d1, d2);

    // Sort pairs
    std::cout << "Sorting pairs:\n";
    int a = 50, b = 10;
    sort_pair(a, b);

    // Concept checks
    std::cout << "\nSwappable checks:\n";
    std::cout << "int: " << std::swappable<int> << "\n";
    std::cout << "string: " << std::swappable<std::string> << "\n";
    std::cout << "vector<int>: " << std::swappable<std::vector<int>> << "\n";
    std::cout << "NoSwap: " << std::swappable<NoSwap> << "\n";

    return 0;
}

// Expected output:
// Swapping ints:
//   Before: a=10, b=20
//   After:  a=20, b=10
// Swapping strings:
//   Before: a=hello, b=world
//   After:  a=world, b=hello
// Swapping doubles:
//   Before: a=1.5, b=9.9
//   After:  a=9.9, b=1.5
// Sorting pairs:
//   Sorted: 10, 50
//
// Swappable checks:
// int: 1
// string: 1
// vector<int>: 1
// NoSwap: 0
Run command
g++ -std=c++20 -Wall -Wextra -o example swappable.cpp