fmt для C++: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение в библиотеку fmt для C++

Библиотека fmt (или fmtlib) — это современная, быстрая и безопасная библиотека для форматирования строк в C++. Она предоставляет альтернативу устаревшим функциям вроде printf и sprintf, а также громоздким потокам std::stringstream. Основная цель fmt — сделать форматирование строк простым, типобезопасным, расширяемым и производительным.

Зачем нужна fmt? Во-первых, она решает проблему безопасности типов. printf не проверяет типы аргументов, что приводит к неопределённому поведению и трудноуловимым багам. fmt же использует шаблоны C++ и проверяет типы на этапе компиляции. Во-вторых, fmt значительно быстрее, чем std::stringstream, и часто быстрее, чем printf. В-третьих, её синтаксис интуитивно понятен и напоминает форматирование в Python, что упрощает переход между языками. Настолько, что fmt стала основой для std::format, который был принят в стандарт C++20.

На этом сайте pythonlib.ru мы часто говорим о Python, но fmt — это отличный пример того, как хорошие идеи из Python перекочевали в мир C++ и стали там стандартом де-факто. Если вы пишете на C++ и хотите делать это современно, fmt — обязательная библиотека в вашем арсенале.

Установка библиотеки fmt

Установка через пакетные менеджеры (Conan, vcpkg)

Самый простой способ установить fmt в современный C++ проект — использовать менеджер пакетов.

Conan:

conan install fmt/10.1.1@
# или в вашем conanfile.txt:
# [requires]
# fmt/10.1.1

vcpkg:

vcpkg install fmt
# Затем в CMakeLists.txt:
# find_package(fmt CONFIG REQUIRED)
# target_link_libraries(your_project PRIVATE fmt::fmt)

Установка вручную (сборка из исходников)

Вы можете скачать исходный код с GitHub и собрать его с помощью CMake:

git clone https://github.com/fmtlib/fmt.git
cd fmt
mkdir build && cd build
cmake ..
make -j4
sudo make install

Установка через pip (для использования в Python-расширениях)

Хотя fmt — это C++ библиотека, её можно установить как Python-пакет, если вы пишете расширение на C++ с использованием pybind11 или cppyy:

pip install fmt

Однако, в контексте чистого C++ это не имеет смысла. Обычно вы просто подключаете заголовочные файлы.

Подключение к проекту (header-only режим)

fmt можно использовать в header-only режиме, просто скопировав папку include/fmt в ваш проект и добавив:

#define FMT_HEADER_ONLY
#include "fmt/core.h"
#include "fmt/format.h"

Быстрый старт с примером кода

Давайте начнём с самого простого примера, который демонстрирует базовое форматирование:

#include <fmt/core.h>
#include <fmt/format.h>
#include <iostream>

int main() {
    // Простейшее форматирование
    std::string message = fmt::format("Привет, {}! Тебе {} лет.", "Мир", 42);
    std::cout << message << std::endl;

    // Вывод в stdout
    fmt::print("Число Пи примерно равно {:.2f}\n", 3.14159);

    // Форматирование с именованными аргументами (C++20 стиль)
    fmt::print("Пользователь: {name}, Возраст: {age}\n",
               fmt::arg("name", "Алиса"),
               fmt::arg("age", 30));

    return 0;
}

Этот код выведет:

Привет, Мир! Тебе 42 лет.
Число Пи примерно равно 3.14
Пользователь: Алиса, Возраст: 30

Как видите, синтаксис {} очень похож на Python. Всё интуитивно и читаемо.

Основные методы и функции библиотеки fmt

Ниже приведён подробный разбор ключевых функций fmt. Мы рассмотрим их сигнатуры, параметры и примеры использования.

1. fmt::format

Описание: Основная функция для форматирования строки. Возвращает std::string.

Параметры:

  • format_string — строка формата (должна быть константой времени компиляции для проверки типов).
  • args... — аргументы для форматирования (переменное количество).

Пример:

#include <fmt/format.h>

int main() {
    std::string result = fmt::format("{} + {} = {}", 2, 3, 2 + 3);
    // result = "2 + 3 = 5"
    fmt::print("Результат: {}\n", result);
    return 0;
}

2. fmt::print

Описание: Форматирует строку и сразу выводит её в стандартный поток вывода (stdout). Аналог printf, но типобезопасный.

Параметры:

  • format_string — строка формата.
  • args... — аргументы для форматирования.

Пример:

#include <fmt/core.h>

int main() {
    fmt::print("Значение: {}\n", 42);
    fmt::print("Шестнадцатеричное: {:X}\n", 255); // Выведет FF
    return 0;
}

3. fmt::format_to

Описание: Форматирует строку и записывает результат в указанный итератор вывода (например, в std::back_inserter).

Параметры:

  • out — итератор вывода.
  • format_string — строка формата.
  • args... — аргументы.

Пример:

#include <fmt/format.h>
#include <vector>

int main() {
    std::vector<char> buf;
    fmt::format_to(std::back_inserter(buf), "Число: {}", 123);
    // buf содержит "Число: 123"
    fmt::print("{}\n", std::string(buf.begin(), buf.end()));
    return 0;
}

4. fmt::format_to_n

Описание: Форматирует строку, но не более чем на n символов. Возвращает результат типа fmt::format_to_n_result, который содержит итератор и количество записанных символов.

Параметры:

  • out — итератор вывода.
  • n — максимальное количество символов для записи.
  • format_string — строка формата.
  • args... — аргументы.

Пример:

#include <fmt/format.h>
#include <array>

int main() {
    std::array<char, 10> buf = {};
    auto result = fmt::format_to_n(buf.begin(), 9, "Длинная строка для обрезки");
    *result.out = '\0'; // Добавляем нуль-терминатор
    fmt::print("Обрезанная строка: '{}'\n", buf.data());
    return 0;
}

5. fmt::formatted_size

Описание: Вычисляет количество символов, которое потребуется для форматирования строки, без фактического форматирования. Полезно для предварительного выделения буфера.

Параметры:

  • format_string — строка формата.
  • args... — аргументы.

Пример:

#include <fmt/format.h>

int main() {
    auto size = fmt::formatted_size("{} + {} = {}", 10, 20, 30);
    fmt::print("Необходимый размер буфера: {}\n", size); // Выведет 12
    return 0;
}

6. fmt::join

Описание: Объединяет элементы контейнера (или диапазона) в строку, разделяя их указанным разделителем. Возвращает объект, который можно передать в fmt::format или fmt::print.

Параметры:

  • range — контейнер или диапазон (должен поддерживать итерацию).
  • delimiter — строка-разделитель.

Пример:

#include <fmt/ranges.h>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    fmt::print("Вектор: [{}]\n", fmt::join(vec, ", "));
    // Вывод: Вектор: [1, 2, 3, 4, 5]
    return 0;
}

7. fmt::arg

Описание: Создаёт именованный аргумент для форматирования. Позволяет использовать имена вместо позиционных индексов.

Параметры:

  • name — строка с именем аргумента.
  • value — значение аргумента.

Пример:

#include <fmt/core.h>

int main() {
    fmt::print("Привет, {name}! Твой ID: {id}\n",
               fmt::arg("name", "Боб"),
               fmt::arg("id", 007));
    // Вывод: Привет, Боб! Твой ID: 7
    return 0;
}

8. fmt::ptr

Описание: Форматирует указатель в читаемый вид (обычно в шестнадцатеричном формате с префиксом 0x).

Параметры:

  • ptr — указатель любого типа.

Пример:

#include <fmt/core.h>

int main() {
    int x = 42;
    fmt::print("Адрес переменной x: {}\n", fmt::ptr(&x));
    // Пример вывода: Адрес переменной x: 0x7ffd5e8b3a4c
    return 0;
}

9. fmt::dynamic_format_arg_store

Описание: Позволяет динамически собирать аргументы для форматирования во время выполнения. Полезно, когда набор аргументов неизвестен на этапе компиляции.

Параметры:

  • Метод push_back для добавления аргументов.
  • Метод format для выполнения форматирования.

Пример:

#include <fmt/format.h>

int main() {
    fmt::dynamic_format_arg_store<fmt::format_context> store;
    store.push_back(fmt::arg("name", "Динамика"));
    store.push_back(fmt::arg("value", 99));
    std::string result = fmt::vformat("Привет                    

Рекомендаций