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;
}