É numeric_limits <int> :: is_modulo logicamente contraditório?
Emoutra pergunta, o tópico destd::numeric_limits<int>::is_modulo
veio. Mas quanto mais eu penso sobre isso, mais parece que algo está errado com a especificação ou com o GCC ou ambos.
Deixe-me começar com algum código:
#include <limits>
#include <iostream>
bool test(int x)
{
return x+1 > x;
}
int main(int argc, char *argv[])
{
int big = std::numeric_limits<int>::max();
std::cout << std::numeric_limits<int>::is_modulo << " ";
std::cout << big+1 << " ";
std::cout << test(big) << "\n";
}
Quando eu compilo isso comg++ -O3 -std=c++11
(x86_64 GCC 4.7.2), produz a seguinte saída:
1 -2147483648 1
Isso é,is_modulo
é verdade, mais umINT_MAX
é negativo e um maisINT_MAX
é melhor queINT_MAX
.
Se você é o tipo de pessoa com alguma chance realista de responder a essa pergunta, já sabe o que aconteceu aqui. A especificação C ++ diz que o estouro de inteiro é Comportamento Indefinido; o compilador tem permissão para assumir que você não faz isso; portanto, o argumento parax+1
não pode serINT_MAX
; portanto, o compilador pode (e irá) compilar otest
função para retornartrue
incondicionalmente. Por enquanto, tudo bem.
No entanto, oEspecificação C ++ 11 também diz (18.3.2.4 parágrafos 60-61):
static constexpr is_modulo;
Verdadeiro se o tipo for modulo.222 Um tipo é modulo se, para qualquer operação envolvendo+
, -
ou*
em valores desse tipo cujo resultado ficaria fora do intervalo[min(),max()]
, o valor retornado difere do valor verdadeiro por um inteiro múltiplo demax() - min() + 1
.
Na maioria das máquinas, isso éfalse
para tipos flutuantes,true
para inteiros não assinados etrue
para inteiros assinados.
Observe que o parágrafo 5 da seção 5 ainda diz: "Se durante a avaliação de uma expressão, o resultado não for matematicamente definido ou não estiver na faixa de valores representáveis para o seu tipo, o comportamento é indefinido." Não há menção deis_modulo == true
criando uma exceção.
Então, parece-me que o padrão é logicamente contraditório, porque o estouro de inteiro não pode ser definido e indefinido simultaneamente. Ou, pelo menos, o GCC não está em conformidade, porque temis_modulo
Comotrue
mesmo que a aritmética assinada certamente não seja envolvida.
O buggy padrão é? O GCC não está em conformidade? Estou esquecendo de algo?