সি ++ তে, কীভাবে কেউ একটি চলকের ধরণ খুঁজে পায়?
সি ++ তে, কীভাবে কেউ একটি চলকের ধরণ খুঁজে পায়?
উত্তর:
আপনি টাইপড অপারেটরটি ব্যবহার করতে পারেন :
#include <typeinfo>
...
cout << typeid(variable).name() << endl;
i
আপনার সংকলকটিতে পূর্ণসংখ্যার অর্থ। ফিরে আসা নামগুলি মান দ্বারা নির্দিষ্ট করা হয় না।
typeid
খুব সংক্ষিপ্ত, সংকলক-নির্দিষ্ট এবং মানুষের ব্যবহারের উদ্দেশ্যে নয়। আপনি "demangle" তাদেরকে (যে প্রকৃত শব্দটি এর!), হয় ভালো কিছু সঙ্গে কোডে gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html যেমন কমান্ড লাইন ইউটিলিটি সঙ্গে c++filt
, অথবা বিভিন্ন অনলাইন demanglers সাথে যেমন demangler.com ।
আপনার যদি ভেরিয়েবল থাকে
int k;
আপনি এর ধরণটি ব্যবহার করে পেতে পারেন
cout << typeid(k).name() << endl;
নিম্নলিখিত থ্রেডটি এসও তে দেখুন: অনুরূপ প্রশ্ন
সি ++ এবং জাভাস্ক্রিপ্টের মধ্যে প্রধান পার্থক্যটি হ'ল সি ++ একটি স্ট্যাটিক-টাইপযুক্ত ভাষা, উইল জাভাস্ক্রিপ্ট গতিশীল।
ডায়নামিক টাইপ করা ভাষাগুলিতে একটি ভেরিয়েবলের মধ্যে যা কিছু থাকে তা থাকতে পারে এবং এর ধরণটি মুহুর্তে মুহুর্তে ধরে রাখা মান দ্বারা দেওয়া হয়। স্ট্যাটিক টাইপ করা ভাষায় ভেরিয়েবলের ধরণ ঘোষিত হয় এবং পরিবর্তন করা যায় না।
ডায়নামিক প্রেরণ এবং অবজেক্ট রচনা এবং সাব টাইপিং (উত্তরাধিকার এবং ভার্চুয়াল ফাংশন) পাশাপাশি স্ট্যাটিক-প্রেরণ এবং সুপারটাইপিং (টেমপ্লেট সিআরটিপি এর মাধ্যমে) হতে পারে, তবে যে কোনও ক্ষেত্রে চলকের ধরণটি অবশ্যই কম্পাইলারের কাছে জানা উচিত।
এটি কী বা কী হতে পারে তা আপনি যদি না জানতে পজিশনে থাকেন তবে ভাষাটির গতিশীল টাইপ-সিস্টেম থাকায় আপনি এমন কিছু নকশা করেছেন।
যদি আপনি সেই ক্ষেত্রে আপনার নকশাকে নতুন করে ভাবতে চেয়েছিলেন তবে যে ভাষাটি আপনি যে ভাষা ব্যবহার করছেন তা প্রাকৃতিক নয় এমন দেশে চলে যাচ্ছে (বেশিরভাগ শুকনো দিয়ে মোটরওয়েতে যাওয়া বা গাড়িতে পানিতে যাওয়ার মতো)
সাধারণত, সি ++ এর মধ্যে একটি ভেরিয়েবলের ধরণটি সন্ধান করা ভুল প্রশ্ন question এটি এমন কিছু হতে পারে যা আপনি পদ্ধতিগত ভাষাগুলির সাথে বহন করেন যেমন উদাহরণস্বরূপ সি বা পাস্কাল।
আপনি যদি টাইপের উপর নির্ভর করে বিভিন্ন আচরণের কোড করতে চান, তবে উদাহরণস্বরূপ ফাংশন ওভারলোডিং এবং অবজেক্টের উত্তরাধিকার সম্পর্কে জানার চেষ্টা করুন । এটি আপনার সি ++ এর প্রথম দিনটিতে তাত্ক্ষণিকভাবে বোঝায় না, তবে এটি চালিয়ে যান।
আমি বিশ্বাস করি যে টাইপড () ব্যবহারের জন্য আমার বৈধ ব্যবহারের কেস রয়েছে, মাপের () ব্যবহার করার জন্য এটি বৈধ। একটি টেমপ্লেট ফাংশনের জন্য, আমাকে টেমপ্লেট ভেরিয়েবলের উপর ভিত্তি করে কোডের বিশেষ কেস করা দরকার, যাতে আমি সর্বাধিক কার্যকারিতা এবং নমনীয়তা সরবরাহ করি।
পলিমারফিজম ব্যবহার না করে প্রতিটি ধরণের সমর্থিত ফাংশনের একটি উদাহরণ তৈরি করা এটি অনেক বেশি কমপ্যাক্ট এবং রক্ষণাবেক্ষণযোগ্য। এমনকি সেই ক্ষেত্রে আমি এই কৌশলটি কেবল একবারে ফাংশনটির বডি লিখতে ব্যবহার করতে পারি:
নোট করুন যেহেতু কোডটি টেমপ্লেটগুলি ব্যবহার করে, নীচে স্যুইচ বিবৃতিটি সমস্ত মিথ্যা কেস, এএফআইকে অপ্টিমাইজ করে শুধুমাত্র একটি কোড ব্লকে স্থিতিশীলভাবে সমাধান করতে হবে।
এই উদাহরণটি বিবেচনা করুন, যেখানে টি রূপের তুলনায় অন্যরকম একটি রূপান্তর পরিচালনা করতে আমাদের প্রয়োজন হতে পারে। আমি এটি ক্লাস স্পেশালাইজেশনের জন্য হার্ডওয়্যার অ্যাক্সেসের জন্য ব্যবহার করি যেখানে হার্ডওয়্যারটি মাই ক্লাসএ বা মাই ক্লাসবি টাইপ ব্যবহার করবে। অমিলের ভিত্তিতে, আমার ডেটা রূপান্তর করতে সময় কাটাতে হবে।
switch ((typeid(T)) {
case typeid(myClassA):
// handle that case
break;
case typeid(myClassB):
// handle that case
break;
case typeid(uint32_t):
// handle that case
break;
default:
// handle that case
}
typeid
সংজ্ঞা অনুসারে - কেবল কোনও স্থিতিশীল, সংকলন-সময় চেক হতে পারে না - সুতরাং এটি কোনও অপ্টিমাইজেশনের সুবিধার্থ করে না। For a template function, I need to special case the code based on the template variable
ঠিক আছে, তাই আপনি যা চান তা হ'ল সিআরটিপি আইডিয়ামের মাধ্যমে স্থির বহুপদীতা। এটি ঠিক যা অর্জন করে।
আমি নিশ্চিত না আমার উত্তরটি সাহায্য করবে কিনা।
সংক্ষিপ্ত উত্তরটি হ'ল, এটি ব্যবহার করার জন্য আপনার আসলে কোনও ভেরিয়েবলের প্রকারটি জানতে / জানতে চান না।
আপনার যদি কোনও স্ট্যাটিক ভেরিয়েবলে কোনও প্রকারের প্রয়োজন হয় তবে আপনি কেবল অটো ব্যবহার করতে পারেন।
আরও পরিশীলিত ক্ষেত্রে যেখানে আপনি ক্লাস বা কাঠামোতে "অটো" ব্যবহার করতে চান, আমি ডিক্লাইপযুক্ত টেম্পলেট ব্যবহারের পরামর্শ দেব।
উদাহরণস্বরূপ, বলুন যে আপনি অন্য কারওের গ্রন্থাগার ব্যবহার করছেন এবং এটিতে "অজানা_ভার" নামে একটি ভেরিয়েবল রয়েছে এবং আপনি এটি কোনও ভেক্টর বা কাঠামোতে রাখতে চান, আপনি এটি সম্পূর্ণরূপে করতে পারেন:
template <typename T>
struct my_struct {
int some_field;
T my_data;
};
vector<decltype(unknown_var)> complex_vector;
vector<my_struct<decltype(unknown_var)> > simple_vector
আশাকরি এটা সাহায্য করবে.
সম্পাদনা: ভাল পরিমাপের জন্য, আমি এখানে সবচেয়ে জটিল বিষয়টি ভাবতে পারি: অজানা প্রকারের একটি বৈশ্বিক পরিবর্তনশীল। এই ক্ষেত্রে আপনার সি ++ 14 এবং টেম্পলেট ভেরিয়েবলের প্রয়োজন হবে।
এটার মতো কিছু:
template<typename T> vector<T> global_var;
void random_func (auto unknown_var) {
global_var<decltype(unknown_var)>.push_back(unknown_var);
}
এটি এখনও কিছুটা ক্লান্তিকর তবে এটি টাইপহীন ভাষাগুলিতে পৌঁছানোর মতোই কাছাকাছি। আপনি যখনই টেম্পলেট পরিবর্তনশীল উল্লেখ করেন কেবলমাত্র তা নিশ্চিত করুন, সর্বদা সেখানে টেমপ্লেটের বিশদকরণ রাখুন।
আপনার যদি কোনও শ্রেণি এবং একটি পরিচিত ধরণের মধ্যে তুলনা করা প্রয়োজন, উদাহরণস্বরূপ:
class Example{};
...
Example eg = Example();
আপনি এই তুলনা লাইন ব্যবহার করতে পারেন:
bool isType = string( typeid(eg).name() ).find("Example") != string::npos;
typeid
নামেরটিতে স্ট্রিং টাইপ রয়েছে কিনা তা যাচাই করে (টাইপড নামটিতে অন্যান্য ম্যাঙ্গেলযুক্ত ডেটা রয়েছে তাই এর s1.find(s2)
পরিবর্তে এটি করা ভাল ==
)।
আপনি অবশ্যই যেতে পারেন typeid(x).name()
যেখানে এক্স পরিবর্তনশীল নাম। এটি প্রকৃতপক্ষে ডেটা টাইপের জন্য একটি চৌম্বক চর পয়েন্টার দেয়। এখন, নীচের কোডটি দেখুন।
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n = 36;
char c = 'A';
double d = 1.2;
if(*(typeid(n).name()) == 'i'){
cout << "I am an Integer variable" << endl;
}
if(*((char *) typeid(d).name()) == 'd'){
cout << "I am a Double variable" << endl;
}
if(*((char *) typeid(c).name()) == 'c'){
cout << "I am a Char variable" << endl;
}
return 0;
}
কিভাবে প্রথম এবং দ্বিতীয় উভয় কাজ করে তা লক্ষ্য করুন।
std::cout << "I'm a variable of type " << typeid(n).name()
। (একটি / একটি শৈলী রোধ করার জন্য শব্দযুক্ত, তবে এটি অন্য চেকের সাহায্যে স্থির করা যেতে পারে)। তবুও, যদি আপনি একেবারে একটি তুলনা চাই, এটা এত ভালো করতে করতেtypeid(n) == typeid(int)