C++20 Comparison

Three-way comparation

C++17

C++
struct A
{
    int x{};
    int y{};
};

bool operator==(const A& left, const A& right)
{
    if(left.x != right.x) return false;
    return left.y == right.x;
}

bool operator!=(const A& left, const A& right)
{
    return !operator==(left, right);
}

bool operator<(const A& left, const A& right)
{
    if(left.x < right.x) return true;
    if(right.x < left.x) return false;
    return left.y < right.y;
}

bool operator<=(const A& left, const A& right)
{
    return left < right || left == right;
}

bool operator>(const A& left, const A& right)
{
    if(left.x > right.x) return true;
    if(right.x > left.x) return false;
    return left.y > right.y;
}

bool operator>=(const A& left, const A& right)
{
    return left > right || left == right;
}

std::ostream& operator<<(std::ostream& os, const A& a)
{
    os << "A{.x=" << a.x << ", .y=" << a.y << "}";
    return os;
}

int main()
{
    auto a0 = A{
        .x = 0, 
        .y = 1,
    };
    auto a1 = A{
        .x = 1,
        .y = 0,
    };

    if(a0 == a1) std::cout << a0 << " == " << a1 << "\n";
    if(a0 != a1) std::cout << a0 << " != " << a1 << "\n";
    if(a0 < a1)  std::cout << a0 << " <  " << a1 << "\n";
    if(a0 <= a1) std::cout << a0 << " <= " << a1 << "\n";
    if(a0 > a1)  std::cout << a0 << " >  " << a1 << "\n";
    if(a0 >= a1) std::cout << a0 << " >= " << a1 << "\n";

    return 0;
}
https://godbolt.org/z/r4PzE3f9v

C++20

C++
struct A
{
    int x{};
    int y{};

    auto operator<=>(const A& other) const = default;
    //friend auto operator<=>(const A& lhs, const A& rhs) = default;
};

std::ostream& operator<<(std::ostream& os, const A& a)
{
    os << "A{.x=" << a.x << ", .y=" << a.y << "}";
    return os;
}

int main()
{
    auto a0 = A{
        .x = 0, 
        .y = 1,
    };
    auto a1 = A{
        .x = 1,
        .y = 0,
    };

    if(a0 == a1) std::cout << a0 << " == " << a1 << "\n";
    if(a0 != a1) std::cout << a0 << " != " << a1 << "\n";
    if(a0 < a1)  std::cout << a0 << " <  " << a1 << "\n";
    if(a0 <= a1) std::cout << a0 << " <= " << a1 << "\n";
    if(a0 > a1)  std::cout << a0 << " >  " << a1 << "\n";
    if(a0 >= a1) std::cout << a0 << " >= " << a1 << "\n";

    return 0;
}
https://godbolt.org/z/jPvK963Ez
Operator<=> is default
https://godbolt.org/z/q1G8qKsds
<=> custom
https://godbolt.org/z/P8bbPE39s
==generatedNOT generated
!=generatedNOT generated
<generatedgenerated
<=generatedgenerated
>generatedgenerated
>=generatedgenerated

Aggregate initialization

C++17

C++
struct A{
    int x;
    int y;
    int z;
};

int main()
{
    A a{0, 1, 2};
    return a.z;
}
https://godbolt.org/z/Wh56sanPo

C++20

C++
struct A{
    int x;
    int y;
    int z;
};

int main()
{
    A a{.x = 0, .y = 1, .z = 2};
    return a.z;
}
https://godbolt.org/z/Wh56sanPo

References

https://en.cppreference.com/w/cpp/language/aggregate_initialization#Designated_initializers

Range-based for loop

C++17

C++
#include <array>
#include <iostream>

int main()
{
    auto i = 0;
    for(auto e : {5, 10, 15})
    {
        std::cout << "value=" << e << " at index=" << i << "\n";
        ++i;
    }
    return 0;
}
https://godbolt.org/z/4se8jT7re

C++20

C++
#include <iostream>

int main()
{
    for(auto i = 0; auto e : {5, 10, 15})
    {
        std::cout << "value=" << e << " at index=" << i << "\n";
        ++i;
    }
    return 0;
}
https://godbolt.org/z/4se8jT7re

Reference

https://en.cppreference.com/w/cpp/language/range-for

[[no_unique_address]], [[likely]], [[unlikely]]

TODO

Lambda capture with an initializer that is a pack expansion

C++17

C++
#include <iostream>

template<typename T>
void increment(T& a)
{
    ++a;
}

template<typename T, typename... Args>
void increment(T& a, Args&... args)
{
    ++a;
    increment(args...);
}

template<typename Callable, typename... Args> 
auto bind(Callable callable, Args&... args)
{
    return [callable, args = std::make_tuple(std::ref(args)...)] {
        std::apply(callable, args);
    };
}

int main()
{
    auto a = 3;
    auto b = 5;
    
    std::cout << "a=" << a << ", b=" << b << "\n";  // a=3, b=5

    auto l = bind(increment<int&, int&>, a, b);

    std::cout << "a=" << a << ", b=" << b << "\n";  // a=3, b=5

    l();

    std::cout << "a=" << a << ", b=" << b << "\n"; // a=4, b=6
    return 0;
}
https://godbolt.org/z/dnGTf58W8

C++20

C++
#include <iostream>

template<typename T>
void increment(T& a)
{
    ++a;
}

template<typename T, typename... Args>
void increment(T& a, Args&... args)
{
    ++a;
    increment(args...);
}

template<typename Callable, typename... Args> 
auto bind(Callable callable, Args&... args)
{
    return [callable, &...args = args]{
        callable(args...);
    };
}

int main()
{
    auto a = 3;
    auto b = 5;
    
    std::cout << "a=" << a << ", b=" << b << "\n";  // a=3, b=5

    auto l = bind(increment<int&, int&>, a, b);

    std::cout << "a=" << a << ", b=" << b << "\n";  // a=3, b=5

    l();

    std::cout << "a=" << a << ", b=" << b << "\n";  // a=4, b=6
    return 0;
}
https://godbolt.org/z/dnGTf58W8

Reference

https://en.cppreference.com/w/cpp/language/lambda#Lambda_capture

consteval

C++17

C++
int f(int a)
{
    return 2 + a;
}

int main()
{
    return f(3);
}
https://godbolt.org/z/7vE7vb3T3
ASM
f(int):
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], edi
        mov     eax, DWORD PTR [rbp-4]
        add     eax, 2
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        mov     edi, 3
        call    f(int)
        nop
        pop     rbp
        ret
https://godbolt.org/z/7vE7vb3T3

C++20

C++
consteval int f(int a)
{
    return 2 + a;
}

int main()
{
    return f(3);
}
https://godbolt.org/z/7vE7vb3T3
ASM
main:
        push    rbp
        mov     rbp, rsp
        mov     eax, 5
        pop     rbp
        ret
https://godbolt.org/z/7vE7vb3T3

Reference

https://en.cppreference.com/w/cpp/language/consteval

<bit>

std::endian

C++
#include <bit>
#include <iostream>

int main()
{
    if constexpr(std::endian::native == std::endian::big)
    {
        std::cout << "std::endian::big\n";
    }
    else
    {
        std::cout << "std::endian::little\n";
    }
    return 0;
}
https://godbolt.org/z/zWYKhTf9v

Leave a Reply

Your email address will not be published. Required fields are marked *