সি ++ টাইপ বৈশিষ্ট্য ব্যবহার করার সময় আমি কিছু অদ্ভুত আচরণের অভিজ্ঞতা পেয়েছি এবং আমার সমস্যাটিকে এই অদ্ভুত সামান্য সমস্যার দিকে সংকুচিত করেছি যার জন্য আমি এক টন ব্যাখ্যা দেব যেহেতু আমি ভুল ব্যাখ্যা দেওয়ার জন্য কিছু খোলা রাখতে চাই না।
বলুন আপনার মতো প্রোগ্রাম রয়েছে:
#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;
}
জিসিসির সাথে 32-বিট সংকলন উভয় (এবং 32- এবং 64-বিট এমএসভিসি সহ), প্রোগ্রামটির আউটপুট হবে:
int: 0
int64_t: 1
long int: 0
long long int: 1
তবে, 64-বিট জিসিসি সংকলনের ফলে প্রোগ্রামটি আউটপুট দেবে:
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
-৪-বিট সংকলনে, 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(যা সি ++ 0 এক্স কনসেপ্টে ব্যবহার করা বেশ সাধারণ):
template <typename T>
void same_type(T, T) { }
void foo()
{
long int x;
long long int y;
same_type(x, y);
}
সেই উদাহরণটি সংকলন করতে ব্যর্থ হয়েছে, যেহেতু সি ++ (সঠিকভাবে) দেখতে পান যে প্রকারগুলি আলাদা। g ++ এর মতো একটি ত্রুটি দিয়ে সংকলন করতে ব্যর্থ হবে: কোনও ফাংশন কল নেই same_type(long int&, long long int&)।
আমি জোর দিয়ে বলতে চাই যে আমি বুঝতে পেরেছি কেন এটি হচ্ছে, তবে আমি এমন একটি কাজের সন্ধান করছি যা পুরো জায়গা জুড়েই কোডটি পুনরাবৃত্তি করতে বাধ্য করে না।
sizeofপ্রতিটি ধরণের জন্য একই ফলাফল দেয় ? সম্ভবত সংকলক আকারের সাথেlong long intআলাদাভাবে আচরণ করছে ।