Chapter 5: Const/Constexpr & String/String_view

Const and Constexpr

C-style Strings

const char* str = ""; // unmodifiable, can't change -> undefined behavior
char str[] = ""; // mutable

std::string

// Incorrect usage
std::string str = "a" + "b"; // not allowed

// Correct usage
std::string str = "a"s + "b" + std::to_string("c") + std::string("d");

Const Type Qualifier

int a { 5 };       // not const at all
const int b { a }; // runtime const (initializer is non-const)
int const c { 5 }; // compile-time const (initializer is a constant expression)

Object-like Macros

#define gravity 9.8

Literal Suffixes

Refer to the Literal Suffixes Table.

Constant Expression

A constant expression is an expression where everything can be evaluated at compile time.

Constexpr Variable

constexpr double gravity { 9.8 };
constexpr int myAge { age }; // compile error: age is not a constant expression

Forced Compile-time Evaluation

#define GFORCE_CONSTEXPR(expr) []() { constexpr auto x = (expr); return x; }()

int global = GFORCE_CONSTEXPR(constexpr_sqrt(42.0));

Definitions

Term Definition
Compile-time constant A value or non-modifiable object whose value must be known at compile time.
Constexpr Keyword declaring variables as compile-time constants and functions for evaluation.
Constant expression An expression containing only compile-time constants and supporting operators.
Runtime expression An expression not classified as a constant expression.
Runtime constant A value or non-modifiable object not classified as a compile-time constant.

Inline Functions and Variables

inline int min(int x, int y) // inline function
{
    return (x < y) ? x : y;
}

Compile-time Evaluation

#include <type_traits> // for std::is_constant_evaluated()

constexpr int someFunction()
{
    if (std::is_constant_evaluated()) // if evaluating in constant context
        doSomething();
    else
        doSomethingElse();
}

Immediate Functions (C++20)

consteval int greater(int x, int y) // function is now consteval
consteval auto compileTimeEval(auto value)

Strings and String Views

std::string

#include <string>
std::string s{"text"}; // class type
s.length();

std::getline for Input

std::string name{};
std::cin >> name; // breaks on whitespace
std::getline(std::cin >> std::ws, name); // ignores leading whitespace

Avoid Passing std::string by Value

void doSomething(const std::string&); // pass by reference

String Literals

namespace std::literals::string_literals
using namespace std::string_view_literals;

#include <string_view>
#include <string>

std::cout << "foo\n";   // C-style string literal
std::cout << "goo\n"s;  // std::string literal
std::cout << "moo\n"sv; // std::string_view literal

// std::string_view can use constexpr, std::string can't
constexpr std::string_view s{ "Hello, world!" }; // s is a string symbolic constant

Dangling std::string_view

#include <iostream>
#include <string>
#include <string_view>

std::string getName()
{
    std::string s{"sdasd"};
    return s;
}

int main()
{
    std::string s { "Alex" };
    std::string_view name { getName() }; // dangling
    std::cout << name << '\n'; // undefined behavior due to out-of-scope
    return 0;
}

std::string_view Guidelines

Modifying std::string Invalidates Views

std::string s { "Hello, world!" };
std::string_view sv { s }; // sv is viewing s

s = "Hello, universe!"; // modifies s, invalidates sv
std::cout << sv << '\n'; // undefined behavior

sv = s; // revalidate sv

Changing Views

std::string_view sv { "Hello" };
sv.remove_prefix(1); // removes 'H'
sv.remove_suffix(1); // removes 'o'

When to Use std::string vs std::string_view

Refer to the Insights on Strings and String Views and When to Use Strings and String Views.