Ir para o conteúdo

Última atualização:2026-10-12

constexpr e a expressão vírgula no C++20

constexpr e comma expr em C++那些事

O C++20 introduziu vários novos recursos, reforçando ainda mais as capacidades em tempo de compilação e a segurança do código. Este artigo explorará em profundidade duas mudanças importantes: o tratamento de exceções em funções constexpr e a descontinuação do operador vírgula dentro do operador de índice.

Obs.: versão para quem tem pressa, os exemplos de código e a documentação relacionada desta seção já foram atualizados no Planeta; junte-se se tiver interesse.

1. A mudança que passa a suportar try-catch em funções constexpr

Antes do C++20, não era possível usar blocos try-catch em funções constexpr; essa limitação impedia o processamento em tempo de compilação de alguns contêineres da biblioteca padrão, como std::array. O C++20 melhorou isso: passa a ser permitido usar blocos try-catch em funções constexpr, e essas estruturas de tratamento de exceções são ignoradas no contexto de expressões constantes. Quando uma exceção é lançada durante a avaliação de uma expressão constante, o compilador reporta um erro.

O principal objetivo dessa mudança é permitir que contêineres da biblioteca padrão, como std::array, ofereçam suporte a constexpr, além de estabelecer a base para dar suporte, no futuro, a mais tratamento de exceções em tempo de compilação.

Exemplo:

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
    }
}

O código acima não compila antes do C++20. Qual é o comportamento do C++20 nesse caso? Tente adivinhar os dois resultados a seguir:

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

2. Descontinuação do operador vírgula dentro do operador de índice

Outra mudança do C++20 é a descontinuação do uso do operador vírgula dentro do operador de índice. Em versões anteriores do C++, na expressão array[x, y], o operador vírgula fazia com que y fosse passado como índice ao array ou contêiner, enquanto x era ignorado. Contudo, esse uso torna o código difícil de entender e atrapalha uma futura implementação de arrays multidimensionais. Por isso, a partir do C++20, o operador vírgula dentro do operador de índice foi descontinuado, a menos que sejam usados parênteses para especificar explicitamente a precedência, como em array[(x, y)].

Código de exemplo:

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

Neste exemplo, arr[(i, j)] usa parênteses para deixar explícita a precedência do operador vírgula, garantindo que j seja passado como índice ao array. No C++17, arr[i, j] é permitido, mas no C++20 esse uso gera um aviso de descontinuação. Dessa forma, é possível garantir um comportamento consistente do código e em conformidade com o novo padrão do C++20.

Se o operador vírgula for usado, o compilador emitirá um aviso:

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 中弃用
      |          ^

Resumo

As mudanças do C++20, em especial o suporte ao tratamento de exceções em funções constexpr e a descontinuação do operador vírgula no operador de índice, visam melhorar as capacidades em tempo de compilação e a legibilidade do código. Se o seu código depende desses recursos antigos, recomenda-se ajustá-lo em tempo hábil para se adaptar ao novo padrão do C++20.

Tópicos relacionados

Comentários