나는 C ++ 유형 특성을 사용하는 동안 이상한 행동을 경험했고 내 문제를이 기발한 작은 문제로 좁혔습니다.
다음과 같은 프로그램이 있다고 가정 해 보겠습니다.
#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;
}
GCC (및 32 비트 및 64 비트 MSVC)를 사용한 32 비트 컴파일에서 프로그램의 출력은 다음과 같습니다.
int: 0
int64_t: 1
long int: 0
long long int: 1
그러나 64 비트 GCC 컴파일 결과 프로그램은 다음을 출력합니다.
int: 0
int64_t: 1
long int: 1
long long int: 0
이후 이것은 호기심 long long int
부호 64 비트 정수와 동일한 모든 의도와 목적을 위해, 인 long int
및 int64_t
종류이므로, 논리적 int64_t
, long int
및 long long int
이러한 유형의 동일 사용시 어셈블리 - 생성 등가 유형 것이다. 한 번 보면 stdint.h
그 이유를 알 수 있습니다.
# if __WORDSIZE == 64
typedef long int int64_t;
# else
__extension__
typedef long long int int64_t;
# endif
64 비트 컴파일에서 int64_t
is long int
, not a long long int
(분명히).
이 상황에 대한 수정은 매우 쉽습니다.
#if defined(__GNUC__) && (__WORDSIZE == 64)
template <>
bool is_int64<long long int>() { return true; }
#endif
그러나 이것은 끔찍하게 해킹되고 잘 확장되지 않습니다 (실체의 실제 기능 uint64_t
등). 그래서 제 질문은 : 컴파일러에게 할 수있는 방법이있는가 long long int
(가)도있다 int64_t
처럼 long int
입니까?
내 초기 생각은 C / C ++ 유형 정의가 작동하는 방식으로 인해 이것이 가능하지 않다는 것입니다. 기본 데이터 유형의 유형 동등성을 컴파일러에 지정하는 방법은 없습니다. 이것이 컴파일러의 작업이고 (많은 것을 허용 할 수 있음) typedef
한 방향으로 만 진행 되기 때문입니다 .
나는 또한 예제가 끔찍하게 고안되지 않았을 때 아무도 신경 쓰지 않을 것이라고 생각하지 않는 초 고급 사례이기 때문에 여기에서 대답을 얻는 데 너무 관심이 없습니다 (이것이 커뮤니티 위키이어야 함을 의미합니까?). .
Append : 다음과 같은 더 쉬운 예제 대신 부분 템플릿 전문화를 사용하는 이유 :
void go(int64_t) { }
int main()
{
long long int x = 2;
go(x);
return 0;
}
은 long long int
암시 적으로 int64_t
.
Append : 지금까지 유일한 대답은 유형이 64 비트인지 알고 싶다고 가정합니다. 나는 사람들이 내가 그것에 관심이 있고 아마도이 문제가 어디에서 나타나는지에 대한 더 많은 예를 제공 했어야한다고 오해하고 싶지 않았습니다.
template <typename T>
struct some_type_trait : boost::false_type { };
template <>
struct some_type_trait<int64_t> : boost::true_type { };
이 예에서, some_type_trait<long int>
될 것입니다 boost::true_type
,하지만 some_type_trait<long long int>
하지 않습니다. 이것은 C ++의 유형 개념에서 의미가 있지만 바람직하지 않습니다.
또 다른 예는 다음과 같은 한정자를 사용하는 것입니다 same_type
(C ++ 0x 개념에서 사용하는 것이 매우 일반적입니다).
template <typename T>
void same_type(T, T) { }
void foo()
{
long int x;
long long int y;
same_type(x, y);
}
이 예제는 컴파일에 실패합니다. C ++는 (올바르게) 유형이 다르다는 것을 인식하기 때문입니다. g ++는 다음과 같은 오류와 함께 컴파일에 실패합니다 : no matching function call same_type(long int&, long long int&)
.
왜 이런 일이 발생 하는지 이해하고 있음을 강조하고 싶지만 여기 저기 코드를 반복하도록 강요하지 않는 해결 방법을 찾고 있습니다.
sizeof
각 유형 에 대해 동일한 결과를 제공 합니까? 아마도 컴파일러는 크기를long long int
다르게 취급하고있을 것입니다 .