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
は、 islong int
であり、long long int
(明らかに) ではありません。
この状況の修正は非常に簡単です。
#if defined(__GNUC__) && (__WORDSIZE == 64)
template <>
bool is_int64<long long int>() { return true; }
#endif
しかし、これはひどくハックであり、うまくスケーリングできません (実体の実際の機能uint64_t
など)。 だから私の質問は次のとおりlong long int
です。コンパイラに aも aint64_t
であることを伝える方法はありlong int
ますか?
私の最初の考えでは、C/C++ の型定義が機能する方法のために、これは不可能であるということです。基本的なデータ型の型等価性をコンパイラに指定する方法はありません。これはコンパイラの仕事であり (そして、それを許可すると多くのことが壊れる可能性があります)、一方向にしか進まないためtypedef
です。
また、ここで回答を得ることにもあまり関心がありません。これは非常に極端なエッジ ケースであり、例がひどく不自然である場合に誰も気にしないと思われるからです (つまり、これはコミュニティ wiki であるべきということですか?)。 .
追加: 次のような簡単な例ではなく、部分的なテンプレートの特殊化を使用している理由:
void go(int64_t) { }
int main()
{
long long int x = 2;
go(x);
return 0;
}
long long int
は暗黙的に に変換可能であるため、上記の例は引き続きコンパイルされint64_t
ます。
追加: これまでの唯一の答えは、型が 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&)
。
なぜこれが起こっているのかを理解していることを強調したいと思いますが、コードをあちこちに繰り返さなくても済む回避策を探しています。