Theme Catppuccin
Make yourself at homeCatppuccin

A softer light for long learning sessions.

Appearance

Loading your preference…

Dark palette

Choose a dark palette to try it.

Light uses Latte. Your choices stay in this browser.

Back to your source shelf

Inside the companion

Modern C++ errors

Follow one pixel through validation, std::expected, and a complete-or-unchanged update.

Project files 6

Validate before publishing

Validate and encode channels, attach an error index, and commit a complete pixel.

39 lines pixel.cpp
#include "pixel/pixel.hpp"
#include <cmath>

namespace pixel {
std::string_view describe(ChannelError error) noexcept {
    switch (error) {
        case ChannelError::non_finite: return "channel must be finite";
        case ChannelError::outside_unit_interval: return "channel must be in [0,1]";
    }
    return "unknown channel error";
}

std::expected<std::uint8_t, ChannelError> encode_channel(double linear) {
    if (!std::isfinite(linear)) return std::unexpected(ChannelError::non_finite);
    if (linear < 0.0 || linear > 1.0)
        return std::unexpected(ChannelError::outside_unit_interval);
    // Validation establishes the finite [0,255] conversion domain.
    return static_cast<std::uint8_t>(std::lround(std::sqrt(linear) * 255.0));
}

std::expected<Pixel, PixelError> prepare_pixel(std::array<double, 3> linear) {
    std::array<std::uint8_t, 3> encoded{};
    for (std::size_t channel = 0; channel < linear.size(); ++channel) {
        const auto result = encode_channel(linear[channel]);
        if (!result) return std::unexpected(PixelError{channel, result.error()});
        encoded[channel] = *result;
    }
    return Pixel{encoded[0], encoded[1], encoded[2]};
}

std::expected<void, PixelError> replace_pixel(
    Pixel& current, std::array<double, 3> linear) {
    const auto candidate = prepare_pixel(linear);
    if (!candidate) return std::unexpected(candidate.error());
    current = *candidate; // Trivial assignment is the commit; it cannot throw.
    return {};
}
}

This is the file included with the course. Copy and download give you its complete source.

Taking your work offline? Download all course companions