EduC++ / Modern C++ Hello World

Modern C++ Hello World

If you learned older C++, this file shows the "new default style" in one place. Classic code often repeated types everywhere, passed strings in ways that copied more than needed, and built output with verbose stream chains.

Modern C++ gives us cleaner tools: - auto (C++11) to remove obvious type repetition - std::string_view (C++17) for non-owning string parameters - structured bindings (C++17) for readable unpacking - std::format (C++20) for safer, clearer formatting

Frequently Asked Questions

QWhen should I NOT use auto?
AAvoid auto when the type is not obvious from the initializer. For example, auto x = foo(); tells the reader nothing about what x is unless they already know foo()'s return type. In public API boundaries and when the type carries important semantic meaning (e.g., size_t vs int), spelling out the type is clearer and safer.
QWhat is the difference between std::string_view and std::string?
Astd::string owns its character data (heap-allocated, copyable, resizable). std::string_view is a non-owning pointer+length pair that refers to characters stored somewhere else. Use string_view for read-only parameters to avoid unnecessary copies. Use string when you need to store or modify the text.
QDoes auto deduce references and const automatically?
ANo. auto strips top-level const and references. If you write auto x = some_const_ref;, x is a mutable copy. To preserve const or reference semantics, write const auto& x = ... or auto& x = ... explicitly.
QIs std::format available in all compilers today?
Astd::format is part of C++20 and is fully supported in MSVC 19.29+ and GCC 13+. Clang/libc++ added full support in Clang 17. If your compiler does not support it yet, the {fmt} library (which inspired std::format) is a drop-in alternative you can use today.
QCan string_view be used with C-style strings (const char*)?
AYes. std::string_view has an implicit constructor from const char*, so you can pass string literals or C strings directly. It will compute the length via strlen. This is one reason string_view works well as a universal read-only string parameter type.
C++
#include <iostream>
#include <string>
#include <string_view>
#include <format>

1 auto -- let the compiler deduce the type

What

auto deduces a variable's type from its initializer expression.

When

Use this when the initializer already makes the type clear.

Why

It removes redundant type spelling while preserving static type safety.

Use

Write auto name = initializer; and use const auto& for non-owning reads.

C++ Version C++11

Read this left to right: "I need a value here; the initializer tells the compiler exactly what type it should be." This makes local code shorter and easier to scan.

Use "const auto&" when you need them preserved.

Watch out: auto strips top-level const and references.

2 string_view -- a lightweight, non-owning view of a string

What

std::string_view is a non-owning view over contiguous characters.

When

Use this for read-only string parameters when ownership should not transfer.

Why

It avoids allocations and copies compared with pass-by-value strings.

Use

Take std::string_view in APIs and ensure referenced storage outlives the view.

C++ Version C++17

Think of string_view as a read-only "window" into text that already exists elsewhere. That makes it a great default for input parameters that only need to read.

Never return a string_view to a local std::string.

Watch out: the viewed string must outlive the string_view.

C++
auto greet(std::string_view name) -> std::string {
    return std::format("Hello, {}! Welcome to Modern C++.", name);
}

3 Trailing return type (auto -> Type)

What

A trailing return type places the return type after the parameter list.

When

Use this when the return type depends on parameters or is clearer at the end.

Why

It improves readability in template-heavy signatures.

Use

Write auto fn(args) -> ReturnType.

C++ Version C++11

For simple functions this is mostly a style choice. For templates and decltype-heavy signatures, it can make declarations much easier to read because the function name appears earlier.

C++
auto add(int a, int b) -> int {
    return a + b;
}

4 Structured bindings (C++17) -- unpack aggregates

What

Structured bindings unpack tuple-like or aggregate values into named variables.

When

Use this when you need readable names for pair/tuple/struct elements.

Why

It removes boilerplate like .first and .second.

Use

Write auto [a, b] = value; or auto& [a, b] = value; to bind by reference.

C++ Version C++17

This is mainly about readability. Instead of "pair.first" and "pair.second", give values meaningful names right away.

Use "auto& [x, y] = ..." to bind by reference.

Watch out: structured bindings create copies by default.

Key Takeaways

  1. Prefer auto when the type is obvious from the initializer.
  2. Use string_view for read-only string parameters to avoid copies.
  3. Use std::format for clear, type-safe string formatting.
  4. Use structured bindings to replace .first/.second boilerplate.
C++
int main() {
    // auto deduces std::string from greet()'s return type
    auto message = greet("World");
    std::cout << message << '\n';

    // Trailing return type -- same result as "int add(int, int)"
    std::cout << std::format("add(3, 4) = {}\n", add(3, 4));

    // Structured bindings: unpack a pair without .first/.second
    auto [x, y] = std::pair{10, 20};
    std::cout << std::format("x = {}, y = {}\n", x, y);

    // Structured bindings with an array
    int arr[] = {100, 200, 300};
    auto [a, b, c] = arr;
    std::cout << std::format("a = {}, b = {}, c = {}\n", a, b, c);

    // const auto& binding -- avoids copying
    const auto& [cx, cy] = std::pair{42, 99};
    std::cout << std::format("cx = {}, cy = {}\n", cx, cy);

    return 0;
}

General Discussion

This lesson feels like a good "new baseline" for writing C++ today. None of the features here are advanced by themselves, but together they make everyday code much easier to read.

The most practical habit to build first is probably string_view for read-only inputs and auto for obvious local variables. Those two changes immediately reduce noise without reducing clarity.

Structured bindings and std::format are mostly readability wins, but they also reduce small mistakes (wrong pair member, formatting mismatch), which adds up over time in real projects.