C ++: long long int vs. long int vs. int64_t

Eu experimentei um comportamento estranho ao usar traços do tipo C ++ e reduzi meu problema a este pequeno problema peculiar, sobre o qual darei uma tonelada de explicações, pois não quero deixar nada em aberto para interpretações errôneas.

Digamos que você tenha um programa assim:

#include <iostream>
#include <cstdint>

template <typename T>
bool is_int64() { return false; }

template <>
bool is_int64<int64_t>() { return true; }

int main()
{
 std::cout << "int:\t" << is_int64<int>() << std::endl;
 std::cout << "int64_t:\t" << is_int64<int64_t>() << std::endl;
 std::cout << "long int:\t" << is_int64<long int>() << std::endl;
 std::cout << "long long int:\t" << is_int64<long long int>() << std::endl;

 return 0;
}

Na compilação de 32 bits com o GCC (e no MSVC de 32 e 64 bits), a saída do programa será:

int:           0
int64_t:       1
long int:      0
long long int: 1

No entanto, o programa resultante de uma compilação do GCC de 64 bits produzirá:

int:           0
int64_t:       1
long int:      1
long long int: 0

Isso é curioso, já quelong long int é um número inteiro de 64 bits assinado e é, para todos os efeitos, idêntico aolong int eint64_t tipos, então logicamente,int64_t, long int elong long int seriam tipos equivalentes - a montagem gerada ao usar esses tipos é idêntica. Uma olhadastdint.h me diz o porquê:

# if __WORDSIZE == 64
typedef long int  int64_t;
# else
__extension__
typedef long long int  int64_t;
# endif

Em uma compilação de 64 bits,int64_t élong int, não umlong long int (obviamente).

A correção para essa situação é bastante fácil:

#if defined(__GNUC__) && (__WORDSIZE == 64)
template <>
bool is_int64<long long int>() { return true; }
#endif

Mas isso é terrivelmente hackish e não escala bem (funções reais da substância,uint64_tetc).Então, minha pergunta é: Existe uma maneira de dizer ao compilador que umlong long int é também oint64_t, Assim comolong int é?

Meu pensamento inicial é que isso não é possível, devido à maneira como as definições de tipo C / C ++ funcionam. Não existe uma maneira de especificar a equivalência de tipo dos tipos de dados básicos para o compilador, pois esse é o trabalho do compilador (e permitir que isso possa quebrar muitas coisas) etypedef só vai de um jeito.

Também não estou muito preocupado em obter uma resposta aqui, já que este é um caso de super-duper que eu não suspeito que alguém se importe quando os exemplos não forem terrivelmente inventados (isso significa que esse deve ser um wiki da comunidade?) .

Acrescentar: A razão pela qual estou usando a especialização parcial de modelos em vez de um exemplo mais fácil, como:

void go(int64_t) { }

int main()
{
    long long int x = 2;
    go(x);
    return 0;
}

é que esse exemplo ainda será compilado, poislong long int é implicitamente conversível em umint64_t.

Acrescentar: A única resposta até agora pressupõe que eu queira saber se um tipo é de 64 bits. Eu não queria induzir as pessoas a pensar que me importo com isso e provavelmente deveria ter fornecido mais exemplos de onde esse problema se manifesta.

template <typename T>
struct some_type_trait : boost::false_type { };

template <>
struct some_type_trait<int64_t> : boost::true_type { };

Neste exemplo,some_type_trait<long int> será umaboost::true_type, massome_type_trait<long long int> não será. Embora isso faça sentido na idéia de tipos do C ++, não é desejável.

Outro exemplo é usar um qualificador comosame_type (que é bastante comum de usar nos conceitos do C ++ 0x):

template <typename T>
void same_type(T, T) { }

void foo()
{
    long int x;
    long long int y;
    same_type(x, y);
}

Esse exemplo falha na compilação, pois o C ++ (corretamente) vê que os tipos são diferentes. O g ++ falhará ao compilar com um erro como: nenhuma chamada de função correspondentesame_type(long int&, long long int&).

Eu gostaria de enfatizar que eu entendoporque isso está acontecendo, mas estou procurando uma solução alternativa que não me force a repetir o código em todo o lugar.

questionAnswers(3)

yourAnswerToTheQuestion