Guidelines Support Library (GSL)

Language: CPP

Utilities

The GSL was originally developed by Microsoft as part of the C++ Core Guidelines project led by Bjarne Stroustrup and Herb Sutter. Its purpose is to provide concrete implementations of safety-oriented types that enforce best practices and help developers write more robust and secure C++ code.

The Guidelines Support Library (GSL) is a set of C++ utilities developed to help programmers follow the C++ Core Guidelines. It provides types and functions such as span, not_null, owner, and utilities for safer memory and pointer usage.

Installation

vcpkg: vcpkg install ms-gsl
conan: conan install gsl-lite
cmake: find_package(Microsoft.GSL CONFIG REQUIRED)

Usage

GSL provides utility types such as span for safe array handling, not_null for non-null pointers, and owner annotations for ownership semantics. It integrates seamlessly with modern C++ projects.

Using span

#include <gsl/span>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};
    gsl::span<int> s(v);
    for (auto x : s) std::cout << x << " ";
    return 0;
}

A `span` provides a safe view over a contiguous sequence of elements without owning them.

Using not_null

#include <gsl/gsl>
#include <iostream>

void process(gsl::not_null<int*> ptr) {
    std::cout << *ptr << std::endl;
}

int main() {
    int x = 42;
    process(&x); // OK
    // process(nullptr); // compile-time error
}

`not_null` enforces at compile time that a pointer cannot be null.

Owner annotations

#include <gsl/gsl>
#include <iostream>

void free_resource(gsl::owner<int*> ptr) {
    delete ptr;
}

int main() {
    gsl::owner<int*> data = new int(10);
    free_resource(data);
}

`owner<T*>` documents ownership semantics and helps static analyzers detect leaks.

Narrow casting

#include <gsl/gsl>
#include <iostream>

int main() {
    int x = 300;
    char c = gsl::narrow<char>(x); // runtime check for narrowing conversion
    std::cout << (int)c << std::endl;
}

`gsl::narrow` performs narrowing casts with runtime checks to prevent unsafe conversions.

Ensuring contracts

#include <gsl/gsl_assert>
#include <iostream>

int divide(int a, int b) {
    Expects(b != 0); // precondition
    return a / b;
}

int main() {
    std::cout << divide(10, 2) << std::endl;
}

Uses `Expects` and `Ensures` macros to declare preconditions and postconditions.

Error Handling

Invalid span access: Ensure the underlying container is not destroyed while span is in use.
Null pointer passed to not_null: Refactor to avoid null usage or wrap with `std::optional` where applicable.
Narrowing cast failed: Use a wider type or validate inputs before applying `narrow`.

Best Practices

Use `span` instead of raw pointers or array references for safe and expressive code.

Mark ownership explicitly using `owner<T*>` to improve readability and analysis.

Use `not_null` whenever null pointers are not valid inputs.

Adopt `narrow` for safe casting between numeric types.

Leverage `Expects` and `Ensures` macros to enforce contracts in critical functions.