C ++ tipi özellikleri kullanırken bazı garip davranışlar yaşadım ve sorunumu, yanlış yorumlamaya açık bir şey bırakmak istemediğim için bir ton açıklama yapacağım bu ilginç küçük soruna indirgedim.
Şöyle bir programınız olduğunu varsayalım:
#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 ile hem 32-bit derlemede (hem de 32- ve 64-bit MSVC ile), programın çıktısı şöyle olacaktır:
int: 0
int64_t: 1
long int: 0
long long int: 1
Ancak, 64 bitlik bir GCC derlemesinden kaynaklanan program şu çıktıyı verecektir:
int: 0
int64_t: 1
long int: 1
long long int: 0
Çünkü bu, meraklı long long int
imzalı 64 bitlik tamsayı olup özdeş tüm niyet ve amaçlar için olduğunu long int
ve int64_t
türleri, bu nedenle mantıklı int64_t
, long int
ve long long int
bu tür özdeş olduğu kullanırken montaj üretilen - eşdeğer tipleri olurdu. Bir bakış stdint.h
bana nedenini anlatıyor:
# if __WORDSIZE == 64
typedef long int int64_t;
# else
__extension__
typedef long long int int64_t;
# endif
64-bit derleme olarak, int64_t
olduğu long int
değil, long long int
(tabii ki).
Bu durumun düzeltilmesi oldukça kolaydır:
#if defined(__GNUC__) && (__WORDSIZE == 64)
template <>
bool is_int64<long long int>() { return true; }
#endif
Ancak bu korkunç derecede hilekar ve iyi ölçeklenmiyor (maddenin gerçek işlevleri uint64_t
, vb.). Yani benim soru: derleyici anlamanın bir yolu var mı bir o long long int
aynı zamanda bir olan int64_t
tıpkı long int
mi?
İlk düşüncelerim, C / C ++ tür tanımlarının çalışma şekli nedeniyle bunun mümkün olmadığıdır. Derleyiciye temel veri türlerinin tür eşdeğerliğini belirlemenin bir yolu yoktur, çünkü bu derleyicinin işidir (ve buna izin vermek birçok şeyi bozabilir) ve typedef
yalnızca tek yönlüdür.
Ayrıca burada bir cevap almakla da ilgilenmiyorum, çünkü bu, örnekler korkunç derecede uydurulmadığında kimsenin umursayacağından şüphelenmediğim süper uç bir durum (bu, bunun topluluk wiki olması gerektiği anlamına mı geliyor?) .
Ek : Aşağıdaki gibi daha kolay bir örnek yerine kısmi şablon uzmanlığı kullanmamın nedeni:
void go(int64_t) { }
int main()
{
long long int x = 2;
go(x);
return 0;
}
söz konusu örneğin long long int
örtük olarak bir int64_t
.
Ek : Şimdiye kadarki tek cevap, bir türün 64 bit olup olmadığını bilmek istediğimi varsayıyor. İnsanları yanıltarak bunu önemsediğimi düşünmek istemedim ve muhtemelen bu sorunun kendini gösterdiği yere dair daha fazla örnek vermeliydim.
template <typename T>
struct some_type_trait : boost::false_type { };
template <>
struct some_type_trait<int64_t> : boost::true_type { };
Bu örnekte, some_type_trait<long int>
olacak boost::true_type
, ancak some_type_trait<long long int>
olmayacak. Bu, C ++ 'ın türler fikrinde mantıklı olsa da arzu edilen bir şey değildir.
Başka bir örnek, same_type
(C ++ 0x Kavramlarında oldukça yaygın olan) gibi bir niteleyici kullanmaktır:
template <typename T>
void same_type(T, T) { }
void foo()
{
long int x;
long long int y;
same_type(x, y);
}
C ++ (doğru şekilde) türlerin farklı olduğunu gördüğünden, bu örnek derlenemez. g ++ aşağıdaki gibi bir hatayla derlenemez: eşleşen işlev çağrısı yok same_type(long int&, long long int&)
.
Bunun neden olduğunu anladığımı vurgulamak isterim , ancak beni her yerde kodu tekrar etmeye zorlamayan bir geçici çözüm arıyorum.
sizeof
her tür için aynı sonuçları veriyor mu? Belki de derleyici boyutunalong long int
farklı davranıyor.