...or the monster that C++ has become.
C++ reinvented itself during the last years, and is barely recognizable now from the good old C++98. It's not like C++ was a simple language back then - quite the contrary. But on top of all this, so many new features have been added that it has become a monster.
And generally speaking, this is a good thing: You now have smart pointers, lambdas, ranges, a chrono library, threads, concepts, modules and so much more. But it can become quite overwhelming with all that new language features additionally. So I created a short overview with a quick (mostly) self explanatory examples, of some of features you might have missed:
Auto |
auto a = 4 + 6; |
Lambdas |
auto aLambda = [](auto a, auto b)
{ return a < b; };
bool b = aLambda(5, 1.23);
|
Strongly typed enums |
enum class
{
value1,
value2
}; |
Static assert |
static_assert( sizeof(x) == 4 ); |
Range based for |
for (auto x : arr)
{
foo(x);
} |
Type alias |
using IntVector = std::vector; |
Unicode strings |
const char* utf8 = u8"foo";
const char16_t* utf16 = u"bar";
const char32_t* utf32 = U"baz"; |
Move and move contructors |
struct X
{
std::string str;
X(): str("foo") { }
X(const X& b) : str(b.str) { }
X(X&& b) noexcept : str(std::move(b.str)) { }
}; |
override |
struct A
{
virtual void foo() {};
};
struct B : public A
{
void foo() override {};
}; |
Designated initializers |
struct A { int x; int y; int z; };
A a { .x = 1, .z = 2 }; |
Modules |
import someModule;
// now use features from that module |
Range based for with init |
int arr[255];
for (int c = 0; auto& x : arr)
{
foo(x, c); ++c;
} |
Auto returns |
auto func(int n)
{
return n + 1;
} |
Consteval |
static consteval int sqr(int n)
{
return n * n;
} |
Constinit |
constinit auto sqrOf5 = sqr(5); |
Concepts |
template
concept IsComparable = requires(T a, T b) {
{ a == b } -> std::same_as;
{ a != b } -> std::same_as;
};
class myclass {
void func(const IsComparable auto& a) { };
}; |
If with initializer |
if (auto p = foobar(); p->value > 1)
{
printf("no");
} |
Switch with initializer |
switch (auto p = foobar(); auto x = p->value)
{
case 0: printf("yes"); break;
case 1: printf("no"); break;
} |
Constexpr if |
if constexpr (sizeof(int) == 1)
return 0; |
Auto template parameters |
template class someclass
{
static auto TConstant = value;
}; |
Space ship operator |
auto operator<=>(const a&) const = default; |
Nested namespace definitions |
namespace A::B::C
{
class myclass { };
} |
Inline variables |
class ClassWithInlineVariable
{
static inline int field = 42;
}; |
Trailing return type |
auto foo(int p) -> int { return p * 42; } |
Decltype |
int n = 33;
decltype(n) t = n+4; |
Structured binding |
int arr[3] = {3,4,5};
auto [x,y,z] = arr;
|
Namespaces with attributes |
namespace [[someAttribute]] myNamespace
{
}; |
Enumerators with attributes |
enum class myEnum
{
value1 [[anAttribute]],
value2 [[anotherAttribute]] = 3
}; |