C++ 20 (general subjects)

span array

void pspan(span<T> s) {
    cout << format("number of elements: {}\n", s.size());
    cout << format("size of span: {}\n", s.size_bytes());
    for(auto e : s) cout << format("{} ", e);
    cout << "\n";
}
int main() {
    int carray[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    pspan<int>(carray);
}

structure binding

int nums[] { 1, 2, 3, 4, 5 };
auto [ a, b, c, d, e ] = nums;
cout << format("{} {} {} {} {}\n", a, b, c, d, e);

array<int,5> nums { 1, 2, 3, 4, 5 };
auto [ a, b, c, d, e ] = nums;
cout << format("{} {} {} {} {}\n", a, b, c, d, e);

tuple<int, double, string> nums{ 1, 2.7, "three" };
auto [ a, b, c ] = nums;
cout << format("{} {} {}\n", a, b, c);

Initialize variables within if and switch statements

template<typename T>
const char * f(const T a) {
    return typeid(T).name();
}
int main() {
    cout << format("T is {}\n", f(47));
    cout << format("T is {}\n", f(47L));
    cout << format("T is {}\n", f(47.0));
    cout << format("T is {}\n", f("47"));
    cout << format("T is {}\n", f("47"s));
}

Use template argument deduction for simplicity and clarity

template<typename T>
const char * f(const T a) {
    return typeid(T).name();
}
int main() {
    cout << format("T is {}\n", f(47));
    cout << format("T is {}\n", f(47L));
    cout << format("T is {}\n", f(47.0));
    cout << format("T is {}\n", f("47"));
    cout << format("T is {}\n", f("47"s));
}
T is int
T is long
T is double
T is char const *

Use if constexpr to simplify compile-time decisions

template<typename T>
auto value_of(const T v) {
    if constexpr (std::is_pointer_v<T>) {
        return *v;  // dereference the pointer
    } else {
        return v;   // return the value
    }
}
int main() {
    int x{47};
    int* y{&x};
    cout << format("value is {}\n", value_of(x));  // value
    cout << format("value is {}\n", value_of(y));  
                                                // pointer
    return 0;
}