Eu estava testando o comportamento dos três grandes (GCC, clang, MSVC). Não tenho certeza do que é compatível com o padrão.
Considere este código:
// p43.cxx
#include <type_traits>
constinit auto n1 = 9223372036854775807; // 2^63 - 1
static_assert(std::is_same_v<decltype(n1), signed long long int>);
constinit auto n2 = 9223372036854775808; // 2^63
constinit auto n3 = 18446744073709551615; // 2^64 - 1
#if defined _MSC_VER || defined __clang__
static_assert(std::is_same_v<decltype(n2), unsigned long long int>);
static_assert(std::is_same_v<decltype(n3), unsigned long long int>);
#elif defined __GNUC__
static_assert(std::is_same_v<decltype(n2), __int128>);
static_assert(std::is_same_v<decltype(n3), __int128>);
#endif
#if defined __GNUC__ && !defined __clang__
constinit auto n4 = 18446744073709551616; // 2^64
static_assert(std::is_same_v<decltype(n4), int>);
#endif
A verificação de sintaxe é aprovada sem erros:
g++ -std=c++2c p43.cxx -Wall -Wextra -Wpedantic -fsyntax-only
clang++ -std=c++2c p43.cxx -Wall -Wextra -Wpedantic -fsyntax-only
cl /nologo /std:c++latest /nologo /Wall /wd4577 p43.cxx /Zs
(para cl
, C4577 está desabilitado para maior clareza)
Visto que usei apenas literais decimais, se entendi corretamente o texto do rascunho atual, [lex.icon]/3 diz que um dos int
, long int
ou long long int
deve ser escolhido. /4 permite usar um tipo inteiro estendido se estes não puderem ser usados, os quais parecem ser diferentes dos padrões conforme [basic.fundamental]/1,2,5 .
Todos os compiladores concordam que n1
é signed long long int
.
Para n2
e n3
, o MSVC não emite avisos, o clang emite este aviso:
aviso: literal inteiro é muito grande para ser representado em um tipo inteiro assinado, interpretando como não assinado`
e o GCC emite o mesmo tipo de aviso que o clang, mas escolhe o tipo estendido (assinado).
A definição n4
só funciona com GCC, mas o tipo nem é o estendido, mas sim int
.
O MSVC e o clang dariam um erro sobre ser muito grande.
Não deveria 9223372036854775808
e 18446744073709551615
seria malformado se signed __int128
não fosse suportado?
O GCC evidentemente suporta __int128
por padrão, mas 18446744073709551616
é transformado em um int
, mesmo que se encaixe em signed __int128
. Por que isso acontece?
Editar (com base no comentário): Não especifiquei minha plataforma. PC Windows x86-64 LLP64