#include <print>

// Alias fuer Funktionstemplate-Zeiger
template <typename T>
using Compare = bool(*)(T&, T&);

// Template-Funktion
// Liefert true zurueck wenn val1<val2
template <typename T>
bool Lesser(T& val1, T& val2)
{
    return val1<val2;
}
// Template-Funktion
// Liefert true zurueck wenn val1>val2
template <typename T>
bool Greater(T& val1, T& val2)
{
    return val1>val2;
}

// Funktion zum Sortieren von int-Daten
// Das Sortierkriterium wird als Template-Funktion uebergeben
template <typename T>
void Sort(int *data, size_t count, Compare<T> pf)
// Alternativ ohne using:
// void Sort(int *data, size_t count, bool(*pf)(T&,T&))
{
    // Einfaches sortieren nach Bubble-Sort
    bool changed;
    do
    {
        changed = false;
        for (size_t i=0; i<count-1; i++)
        {
            // Aufruf der Vergleichsfunktion!!
            if (!(*pf)(data[i],data[i+1]))
            {
                int temp = data[i];
                data[i] = data[i + 1];
                data[i + 1] = temp;
                changed = true;
            }
        }
    } while (changed);
}

// main() Funktion
int main()
{
    // int-Feld definieren
    constexpr auto SIZE=10;
    int iarray[SIZE];
    // und mit Zufallszahlen belegen und ausgeben
    std::println("Ausgangsfeld:");
    for (auto& e: iarray)
    {
        e = std::rand()%100;
        std::print("{},", e);
    }
    std::println("");
    // int-Feld sortieren, Sortierkriterium wird ueber
    // Template-Funktion festgelegt
    std::println("Aufsteigend sortiert:");
    Sort(iarray, SIZE, Lesser<int>);
    // int-Feld erneut ausgeben
    for (auto e : iarray)
        std::print("{},", e);
    std::println("");
    // Sortierrichtung absteigend
    std::println("Fallend sortiert:");
    Sort(iarray, SIZE, Greater<int>);
    // int-Feld erneut ausgeben
    for (auto e: iarray)
        std::print("{},", e);
    std::println("");
}
