// C++23 - std::to_underlying, autor: Władysław Młynik
//
// Przykład użycia std::to_underlying z enumeracją kolorów w formacie RGBA
// 
// std::to_underlying to funkcja wprowadzona w standardzie C++23, która pozwala na uzyskanie wartości bazowej (underlying value)
// z typu wyliczeniowego (enum). Dzięki temu można bezpośrednio uzyskać reprezentację liczbową wartości wyliczeniowej.
// W poniższym przykładzie, std::to_underlying jest wykorzystane do konwersji wartości wyliczeniowych reprezentujących kolory w formacie
// RGBA na ich wartości liczbowe, które są następnie wyświetlane w formacie heksadecymalnym.
//
// Przykład można skompilować poleceniem:
//      g++ -std=c++23 to_underlying.cpp -o to_underlying

#include <iostream>
#include <iomanip>
#include <bit>
#include <utility>
#include <cstdint>

// Definicja enum class reprezentującego kolory w formacie RGBA
enum class Color : uint32_t
{
    Red   = 0xFF0000FF,  // 0xFF0000FF reprezentuje kolor czerwony w formacie RGBA
    Green = 0x00FF00FF,  // 0x00FF00FF reprezentuje kolor zielony w formacie RGBA
    Blue  = 0x0000FFFF,  // 0x0000FFFF reprezentuje kolor niebieski w formacie RGBA
    White = 0xFFFFFFFF,  // 0xFFFFFFFF reprezentuje kolor biały w formacie RGBA
    Black = 0x000000FF   // 0x000000FF reprezentuje kolor czarny w formacie RGBA
};

// Operator do wyświetlania kolorów
// Wykorzystuje std::to_underlying do konwersji z typu Color na typ uint32_t, którego wartość można wypisać
std::ostream& operator<<(std::ostream& os, Color color)
{
    uint32_t value = std::to_underlying(color); // Użycie std::to_underlying do uzyskania wartości bazowej typu wyliczeniowego
    os << "0x" << std::hex << std::setw(8) << std::setfill('0') << value; // Konwersja wartości na heksadecymalny string i wypisanie
    return os;
}

int main()
{
    // Wyświetlenie wartości bazowych kolorów
    std::cout << "Red: " << Color::Red << "\n";
    std::cout << "Green: " << Color::Green << "\n";
    std::cout << "Blue: " << Color::Blue << "\n";
    std::cout << "White: " << Color::White << "\n";
    std::cout << "Black: " << Color::Black << "\n";

    return 0;
}

// MAteriały:
// https://en.cppreference.com/w/cpp/utility/to_underlying
// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1682r2.html