C 17 Lang Cheatsheet
C 17 Lang Cheatsheet
Template argument deduction for class templates Lambda capture this by value constexpr if
pair p1(1, 2.0); struct foo { template <typename T> int compute(T x) {
// vs foo() : _x{0} {} // no () around consexpr
pair<int, double> p2(1, 2.0); int _x; if constexpr (std::is_integral<T>::value) {
auto log_by_ref() { return x * x;
Declaring non-type template parameters with auto return [this]() { cout << _x << endl; }; } else if constexpr (is_same<T, string>::value) {
} return x.size();
template <auto ... seq> auto log_by_val() { } else if constexpr (is_base_of<foo, T>::value) {
struct my_integer_sequence { return [*this]() { cout<<_x<<endl;}; x.bar();
// Implementation here ... } return 0;
}; }; }
// Explicitly pass type `int` as template argument. struct foo f; return 0;
auto seq = std::integer_sequence<int, 0, 1, 2>(); auto ref = f.log_by_ref(); }
// Type is deduced to be `int`. auto val = f.log_by_val();
auto seq2 = my_integer_sequence<0, 1, 2>(); f._x = 1234; Hexadecimal floating-point literals
ref(); val(); // both 1234
Folding expressions f._x = 4321; cout << 0x10.1p0 << endl // 16.0625
ref(); // 4321 << 0X0.8p0 << endl // 0.5
template<typename ... Ts> val(); // 1234 << 0X50.8p5 << endl; // 2576
auto sum_fold_exp(const Ts& ... ts) {
return (ts + ...); Inline variables Direct List Initialization of Enums
}
template<typename ... Ts> struct S { int x; }; // underlying type must be fixed (char here)
auto print_fold(const Ts& ... ts) inline S x1 = S{321}; enum class color : char { red, blue, green };
{ // must be non-narrowing, i.e 129 is an error
((cout << ts << " "), ... ); color c1 { 3 }, c2 { 88 };
}
Nested namespaces
namespace A::B::C { [[fallthrough]] attribute
New rules for auto deduction from braced-init-list class foo;
} switch (i) {
// error: not a single element case 1: cout<<"one"<<endl; // warning
auto x1{ 1, 2, 3 }; case 2: cout<<"two"<<endl;
// decltype(x2) is std::initializer_list<int> Structured bindings [[fallthrough]];
auto x2 = { 1, 2, 3 }; case 3 : cout<<"three"<<endl; // warning supressed
// decltype(x3) is int, previously deduced to template<typename T> }
// initializer_list<int> pair<T, bool> racine(T d) {
auto x3{ 3 }; if (d<0) return pair(-1, false);
return pair(sqrt(d), true); [[nodiscard]] attribute
// decltype(x4) is double
auto x4{ 3.0 }; } Can be applied to a type (function with that return type will be marked
as [[nodiscard]])
constexpr lambda auto [s, success] = racine(1998.0);
if (success) cout << s << endl; [[nodiscard]] int foo() { return 1; };
void bar() {
auto identity = [] (int n) constexpr { return n; }; foo(); // Warning
static_assert(identity(123) == 123); Initializers in if and switch statements
constexpr int addOne(int n) { if (auto res=m.insert({key,value}); res.second) { [[maybe_unused]] attribute
return [n] { return n + 1; }(); cout<<key<<"/"<<value<<" inserted"<<endl;
} } [[maybe_unused]] static void f() {} // No warning
static_assert(addOne(1) == 2); [[maybe_unused]] int x = 42; // No warning
Removal of trigraphs
static_assert without message
UTF-8 Character Literals
??= ??/ ??' ??( ??) ??! ??< ??> ??- static_assert(VERSION >= 2);
char x = u8'x';