पाठ 15 / 25

Vocabulary Types: optional, variant, string_view and span

Use modern vocabulary types to express intent safely.

Types that say what you mean

Modern C++ added small "vocabulary" types that make interfaces clearer and safer. std::optional<T> (C++17) represents a value that may be absent, replacing sentinel values such as -1 or null pointers: std::optional<User> find_user(int id). std::variant<A, B, C> (C++17) holds exactly one of several types, a type-safe union; inspect it with std::visit or std::holds_alternative. std::string_view (C++17) is a non-owning view of characters, ideal for read-only string parameters because it accepts std::string, literals and substrings without copying; it must not outlive the data it refers to. std::span<T> (C++20) is a non-owning view of a contiguous sequence (vector, array, C array). std::pair and std::tuple group values, and structured bindings (auto [name, marks] = pair;) unpack them. std::expected<T, E> (C++23) returns either a value or an error. Using these types documents intent in the type system instead of comments.

Vocabulary types in function interfaces

Absence, alternatives and views are explicit in the signatures.

#include <optional>
#include <span>
#include <string>
#include <string_view>
#include <type_traits>
#include <variant>
#include <vector>

std::optional<int> parse_marks(std::string_view text) {    // accepts literals and strings, no copy
    int value = 0;
    for (char ch : text) {
        if (ch < '0' || ch > '9') return std::nullopt;     // explicit "no value"
        value = value * 10 + (ch - '0');
    }
    return value <= 100 ? std::optional<int>{value} : std::nullopt;
}

double average(std::span<const int> values) {               // vector, array or C array
    double sum = 0;
    for (int v : values) sum += v;
    return values.empty() ? 0.0 : sum / values.size();
}

using Payment = std::variant<std::string /* UPI id */, long long /* card last digits */>;

std::string describe(const Payment& p) {
    return std::visit([](const auto& v) -> std::string {
        if constexpr (std::is_same_v<std::decay_t<decltype(v)>, std::string>) return "UPI " + v;
        else return "card ending " + std::to_string(v);
    }, p);
}

int main() {
    if (auto m = parse_marks("87")) { /* *m is 87 */ }
    std::vector<int> v{70, 80, 90};
    double avg = average(v);
}

Views must not outlive their data

Returning a std::string_view or std::span that refers to a local string or vector creates a dangling view. Use views for parameters; return owning types such as std::string and std::vector.

त्वरित जाँच: Which type best expresses "a function may or may not return an integer"?

  • int with -1 as a special value
  • std::variant<int, int>
  • std::optional<int>
  • int*
Answer

std::optional<int> — std::optional makes absence explicit in the type instead of relying on magic values.