Перейти к содержанию

Последнее обновление:2026-10-12

constexpr и оператор «запятая» в C++20

C++那些事 — constexpr и comma expr

C++20 привнёс ряд новых возможностей, дополнительно усиливших возможности времени компиляции и безопасность кода. В этой статье мы подробно разберём два важных изменения: обработку исключений в constexpr-функциях и deprecated-статус оператора «запятая» в операторе индексации.

Примечание: для ленивых — примеры кода и сопутствующие документы этого раздела уже выложены в сообществе (知识星球), присоединяйтесь, если интересно.

1. Изменение: поддержка обработки исключений try-catch в constexpr-функциях

До C++20 в constexpr-функциях нельзя было использовать блоки try-catch, и это ограничение мешало обработке на этапе компиляции для ряда контейнеров стандартной библиотеки, таких как std::array. C++20 улучшил это: разрешено использовать блоки try-catch в constexpr-функциях, причём в контексте константных выражений эти конструкции обработки исключений игнорируются. Если при вычислении константного выражения бросается исключение, компилятор сообщит об ошибке.

Главная цель этого изменения — позволить контейнерам стандартной библиотеки, например std::array, поддерживать constexpr, а также заложить основу для более полной поддержки обработки исключений на этапе компиляции в будущем.

Пример:

constexpr int SafeDivide(int a, int b) {
    if (b == 0) {
        throw std::runtime_error("Division by zero!");  // 当除数为0时抛出异常
    }
    return a / b;
}

constexpr int ComputeQuotient(int x) {
    try {
        return SafeDivide(100, x);  // 尝试除法运算
    } catch (const std::runtime_error&) {
        return -1;  // 捕获除零异常并返回 -1
    }
}

Приведённый выше код не компилировался до C++20; как C++20 обрабатывает это поведение — можете попробовать угадать результаты двух следующих проверок:

static_assert(ComputeQuotient(25) == 4); 
static_assert(ComputeQuotient(0) == -1); 

2. Deprecated-статус оператора «запятая» в операторе индексации

Другое изменение в C++20 — deprecated-статус оператора «запятая» внутри оператора индексации. В ранних версиях C++ в выражении array[x, y] оператор «запятая» приводил к тому, что в качестве индекса массиву или контейнеру передавался y, а x игнорировался. Однако такое использование делает код трудным для понимания и мешает будущей реализации многомерных массивов. Поэтому начиная с C++20 оператор «запятая» в операторе индексации объявлен deprecated, если только приоритет не задан явно скобками, как в array[(x, y)].

Пример кода:

// arr[i, j] = 10;  // C++17 中合法,C++20 中弃用
arr[(i, j)] = 10;  // 使用括号以明确逗号的优先级

В этом примере arr[(i, j)] использует скобки, чтобы явно задать приоритет оператора «запятая» и гарантировать, что именно j передаётся массиву в качестве индекса. В C++17 запись arr[i, j] была допустима, но в C++20 такое использование вызывает предупреждение о deprecated. Таким образом можно обеспечить единообразное поведение кода и соответствие новому стандарту C++20.

Если использовать оператор «запятая», компилятор выдаст предупреждение:

common.cc:9:10: warning: top-level comma expression in array subscript is deprecated [-Wcomma-subscript]
    9 |     arr[i, j] = 10;  // C++17 中合法,C++20 中弃用
      |          ^

Итоги

Изменения в C++20 — в частности, поддержка обработки исключений в constexpr-функциях и deprecated-статус оператора «запятая» в операторе индексации — направлены на повышение возможностей времени компиляции и читабельности кода. Если ваш код опирается на эти старые возможности, рекомендуется своевременно его скорректировать, чтобы он соответствовал новому стандарту C++20.

Похожие темы

Комментарии