मैंने 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
है long int
न एक, 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
है?
मेरे शुरुआती विचार हैं कि यह संभव नहीं है, जिस तरह से सी / सी ++ प्रकार की परिभाषाएं काम करती हैं। कंपाइलर के लिए बुनियादी डेटा प्रकारों के प्रकार को निर्दिष्ट करने का कोई तरीका नहीं है, क्योंकि यह कंपाइलर का काम है (और यह अनुमति देता है कि बहुत सी चीजों को तोड़ सकता है) और typedef
केवल एक ही रास्ता जाता है।
मैं यहां एक उत्तर पाने से भी चिंतित नहीं हूं, क्योंकि यह एक सुपर-डुपर एज मामला है कि मुझे संदेह नहीं है कि किसी को भी इस बात की परवाह होगी कि जब उदाहरण बुरी तरह से वंचित न हों (क्या इसका मतलब यह समुदाय विकि होना चाहिए?) ।
परिशिष्ट : इस कारण से कि मैं एक आसान उदाहरण के बजाय आंशिक टेम्पलेट विशेषज्ञता का उपयोग कर रहा हूं:
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>
नहीं होगा। हालांकि यह सी ++ के प्रकारों के बारे में सोचता है, यह वांछनीय नहीं है।
एक अन्य उदाहरण एक क्वालीफायर का उपयोग कर रहा है जैसे 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 ++ एक त्रुटि के साथ संकलित करने में विफल रहेगा जैसे: कोई मिलान फ़ंक्शन कॉल नहीं same_type(long int&, long long int&)
।
मैं इस बात पर जोर देना चाहूंगा कि मुझे समझ में आ रहा है कि ऐसा क्यों हो रहा है, लेकिन मैं ऐसे वर्कअराउंड की तलाश कर रहा हूं जो मुझे सभी जगह कोड दोहराने के लिए मजबूर न करे।
sizeof
प्रत्येक प्रकार के लिए समान परिणाम देता है ? शायद संकलकlong long int
अलग-अलग आकार का इलाज कर रहा है ।