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/r4PzE3f9vC++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/jPvK963EzOperator | <=> is default https://godbolt.org/z/q1G8qKsds | <=> custom https://godbolt.org/z/P8bbPE39s |
---|---|---|
== | generated | NOT generated |
!= | generated | NOT generated |
< | generated | generated |
<= | generated | generated |
> | generated | generated |
>= | generated | generated |
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/Wh56sanPoC++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/Wh56sanPoReferences
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/4se8jT7reC++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/4se8jT7reReference
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/dnGTf58W8C++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/dnGTf58W8Reference
https://en.cppreference.com/w/cpp/language/lambda#Lambda_capture
consteval
C++17
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/7vE7vb3T3C++20
C++
consteval int f(int a)
{
return 2 + a;
}
int main()
{
return f(3);
}
https://godbolt.org/z/7vE7vb3T3Reference
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