এই টেমপ্লেট কোডটি কীভাবে একটি অ্যারের কাজের আকার পেতে পারে?


61

আমি ভাবছি কেন এই ধরণের কোড পরীক্ষা অ্যারের আকার পেতে পারে? আমি টেমপ্লেটে ব্যাকরণের সাথে পরিচিত নই। হয়তো কেউ এর অধীনে কোডটির অর্থ ব্যাখ্যা করতে পারে template<typename,size_t>। এছাড়াও, একটি রেফারেন্স লিঙ্কটিও পছন্দ করা হয়।

#define dimof(array) (sizeof(DimofSizeHelper(array)))
template <typename T, size_t N>
char(&DimofSizeHelper(T(&array)[N]))[N];

void InitDynCalls()
{
    char test[20];
    size_t n = dimof(test);
    printf("%d", n);
}


আপনি সি ++ 11 সম্পর্কে n3337 এর মতো কিছু পড়েছেন ? এটি আপনার প্রশ্নের সাথে প্রাসঙ্গিক হওয়া উচিত! আপনি কি ব্যবহারের কথা বিবেচনা করেছেন বা ....std::arraystd::vector
বেসিল স্টারিনকিভিচ

পুনঃটুইট কোডটি তৃতীয় পক্ষের লাইব্রেরিতে প্রদর্শিত হবে। আমি শুধু অর্থটি বের করতে চাই।
ছায়া অবধি

দরকারী অন্তর্দৃষ্টি (এবং দেখুন যে পৃষ্ঠার লেখক কে দেখুন) জন্য norvig.com/21-days.html দেখুন ।
বেসিল স্টারিনকিভিচ

2
দেখে মনে হচ্ছে স্টকওভারফ্লো
ডাব্লিকেট

@ বাসাইলস্টারিঙ্কেভিচ আমি এই লিঙ্কটির প্রাসঙ্গিকতা বুঝতে পারি না।
অরবিটে হালকা ঘোড়দৌড়

উত্তর:


86

এটি ব্যাখ্যা করা আসলেই খুব শক্ত, তবে আমি এটি দিয়ে যাব ...

প্রথমত, dimofআপনাকে অ্যারের মধ্যে মাত্রা বা উপাদানগুলির সংখ্যা বলে tells (আমি বিশ্বাস করি উইন্ডোজ প্রোগ্রামিং পরিবেশে "মাত্রা" পছন্দসই পরিভাষা)।

এটি প্রয়োজনীয় কারণ C++এবং Cআপনাকে অ্যারের আকার নির্ধারণের জন্য কোনও দেশীয় উপায় দেয় না।


প্রায়শই লোকেরা ধরে sizeof(myArray)নেবে কাজ করবে তবে এটি উপাদানগুলির সংখ্যার চেয়ে আসলে আপনাকে মেমরির আকার দেবে। প্রতিটি উপাদান সম্ভবত 1 বাইট মেমরি লাগে!

পরবর্তী, তারা চেষ্টা করতে পারে sizeof(myArray) / sizeof(myArray[0])। এটি অ্যারের স্মৃতিতে আকার দেবে, প্রথম উপাদানটির আকার দ্বারা বিভক্ত। এটি ঠিক আছে, এবং Cকোডে বহুল ব্যবহৃত । এটির সাথে প্রধান সমস্যাটি হ'ল আপনি যদি অ্যারের পরিবর্তে কোনও পয়েন্টারটি পাস করেন তবে এটি কাজ করবে। মেমোরিতে একটি পয়েন্টারের আকারটি সাধারণত 4 বা 8 বাইট হতে হবে, যদিও এটি যে জিনিসটিকে নির্দেশ করে তা হ'ল উপাদানগুলির একটি অ্যারে হতে পারে।


সুতরাং চেষ্টা করার পরবর্তী জিনিস C++হ'ল টেমপ্লেটগুলি এমন কিছু বল প্রয়োগ করার জন্য ব্যবহার করা যা কেবল অ্যারেগুলির জন্য কাজ করে এবং একটি পয়েন্টারে সংকলক ত্রুটি দেয়। দেখে মনে হচ্ছে:

template <typename T, std::size_t N>
std::size_t ArraySize(T (&inputArray)[N])
{
    return N;
}
//...
float x[7];
cout << ArraySize(x); // prints "7"

টেমপ্লেটটি কেবল একটি অ্যারের সাথে কাজ করবে। এটি প্রকারটি (আসলে প্রয়োজন হয় না, তবে কাজ করতে টেমপ্লেটটি পেতে সেখানে উপস্থিত থাকতে হবে) এবং অ্যারের আকারটি হ্রাস করবে, তারপরে এটি আকারটি দেয়। টেমপ্লেটটি যেভাবে লিখিত হয়েছে সম্ভবত পয়েন্টার দিয়ে কাজ করতে পারে না।

সাধারণত আপনি এখানে থামতে পারেন, এবং এটি সি ++ স্ট্যান্ডার্ড লিবারিতে রয়েছে std::size


সতর্কতা: নীচে এটি লোমশ ভাষা-আইনী অঞ্চলে যায়।


এটি বেশ দুর্দান্ত, তবে এখনও একটি অস্পষ্ট প্রান্ত ক্ষেত্রে ব্যর্থ:

struct Placeholder {
    static float x[8];
};

template <typename T, int N>
int ArraySize (T (&)[N])
{
    return N;
}

int main()
{
    return ArraySize(Placeholder::x);
}

মনে রাখবেন যে, অ্যারের xহয় ঘোষিত , কিন্তু না সংজ্ঞায়িত । এটির সাথে কোনও ফাংশন (অর্থাত্ ArraySize) কল করতে xঅবশ্যই সংজ্ঞা দিতে হবে

In function `main':
SO.cpp:(.text+0x5): undefined reference to `Placeholder::x'
collect2: error: ld returned 1 exit status

আপনি এটি লিঙ্ক করতে পারবেন না।


আপনার প্রশ্নে কোডটি চারপাশের উপায়। প্রকৃতপক্ষে কোনও ফাংশন কল করার পরিবর্তে আমরা একটি ফাংশন ঘোষণা করি যা সঠিক আকারের একটি অবজেক্ট দেয় । তারপরে আমরা সেই sizeofকৌশলটি ব্যবহার করি।

এটা তোলে দেখায় হচ্ছে আমরা ফাংশন কল, কিন্তু sizeofতাই ফাংশন আসলে বলা হয়, একটি সময় সঙ্কলন কনস্ট্রাক্ট বিশুদ্ধরূপে হয়।

template <typename T, size_t N>
char(&DimofSizeHelper(T(&array)[N]))[N];
^^^^ ^                               ^^^
// a function that returns a reference to array of N chars - the size of this array in memory will be exactly N bytes

নোট করুন আপনি আসলে কোনও ফাংশন থেকে কোনও অ্যারে ফিরিয়ে দিতে পারবেন না তবে আপনি কোনও অ্যারের রেফারেন্স দিতে পারেন।

তারপরে DimofSizeHelper(myArray)একটি অভিব্যক্তি যা এর টাইপN char গুলি এর উপর একটি অ্যারে । এক্সপ্রেশনটি আসলে রানযোগ্য হতে হবে না, তবে সংকলনের সময় এটি বোধগম্য।

অতএব sizeof(DimofSizeHelper(myArray))আপনি সংকলনের সময় আকারটি আপনাকে বলবেন যদি আপনি আসলে ফাংশনটি কল করেন তবে আপনি কী পাবেন। যদিও আমরা আসলে এটি কল করি না।

অস্টিন শক্তি ক্রস আইড


যদি এই শেষ ব্লকটি কোনও অর্থবোধ না করে তবে চিন্তা করবেন না। উদ্ভট প্রান্তের কেসটি ঘিরে কাজ করা একটি উদ্ভট কৌশল। এ কারণেই আপনি নিজেরাই এই ধরণের কোডটি লেখেন না এবং লাইব্রেরি প্রয়োগকারীরা এই ধরণের বাজে কথা সম্পর্কে উদ্বিগ্ন হন।


3
@ Shadowfiend- এটিও ভুল। বিষয়গুলি তার চেয়েও খারাপ।
BoBTFish

5
এটি কোনও ফাংশন রেফারেন্সের ঘোষণা কেন? "ডিমোফসিজহেল্পার" এর আগে "এবং" এর অর্থ ফেরতের ধরণটি চর (এবং) [এন], বোলভের উত্তরের সাথে মিল রেখে।
ছায়া অবধি

3
পছন্দ করুন আমি শুধু আবর্জনা বলছিলাম কারণ আমার মস্তিষ্ক একটি গিঁটে বাঁধা ছিল।
BoBTFish

মাত্রা কোনও অ্যারের উপাদানের সংখ্যা নয়। এটি হ'ল আপনার কাছে 1, 2, 3 বা উচ্চতর মাত্রিক অ্যারে থাকতে পারে, যার প্রতিটিতে একই সংখ্যক উপাদান থাকতে পারে। যেমন অ্যারে 1 ডি [1000], অ্যারে 2 ডি [10] [100], অ্যারে 3 ডি [10] [10] [10] 10 প্রতিটিতে 1000 টি উপাদান রয়েছে।
জামেস্কেফ

1
@ জামেস্কফ সি সি ++ এর মতো ভাষায়, একটি বহুমাত্রিক অ্যারে কেবল একটি অ্যারে যা অন্যান্য অ্যারে ধারণ করে। সংকলকের দৃষ্টিকোণ থেকে, প্রাথমিক অ্যারেতে উপাদানগুলির সংখ্যা প্রায়শই সম্পূর্ণরূপে এর বিষয়বস্তুর সাথে সম্পর্কিত হয় না - যা গৌণ বা তৃতীয় অ্যারে হতে পারে।
ফিলারেক্স

27
template <typename T, size_t N>
char(&DimofSizeHelper(T(&array)[N]))[N];

// see it like this:
//                char(&DimofSizeHelper(T(&array)[N]))[N];
// template name:       DimofSizeHelper
// param name:                             array
// param type:                          T(&     )[N])
// return type:   char(&                             )[N];

DimofSizeHelperএটি একটি টেমপ্লেট ফাংশন যা একটি T(&)[N]প্যারামিটার গ্রহণ করে - ওরফে এন টাইপের এন উপাদানগুলির সি-অ্যারের একটি রেফারেন্স Tএবং একটি char (&)[N]ওরফে এন অক্ষরের অ্যারে রেফারেন্স প্রদান করে। সি ++ এ একটি চর ছদ্মবেশে বাইট হয় এবং এটি স্ট্যান্ডার্ডের দ্বারা sizeof(char)গ্যারান্টিযুক্ত হয় 1

size_t n = dimof(test);
// macro expansion:
size_t n = sizeof(DimofSizeHelper(array));

nরিটার্নের ধরণের আকার নির্ধারিত DimofSizeHelperহয় sizeof(char[N])যা কোনটি N


এটি কিছুটা সংশ্লেষিত এবং অপ্রয়োজনীয়। এটি করার স্বাভাবিক উপায় ছিল:

template <class T, size_t N>
/*constexpr*/ size_t sizeof_array(T (&)[N]) { return N; }

যেহেতু সি ++ 17 এটি অপ্রয়োজনীয়, আমাদের যেমন std::sizeএটি করে তবে এটি আরও সাধারণ উপায়ে যে কোনও স্টাইল-স্টাইলের ধারক আকার পেতে সক্ষম।


BoBTFish দ্বারা চিহ্নিত হিসাবে, এটি একটি এজ কেস জন্য প্রয়োজনীয়।


2
আপনি যদি আকারটি নিতে চান সেই অ্যারেটি ওডিআর-ব্যবহার করতে না পারেন তবে এটি প্রয়োজনীয় (এটি ঘোষিত তবে সংজ্ঞায়িত নয়)। স্বীকার করা, বেশ অস্পষ্ট।
BoBTFish

টেম্পলেট ফাংশন টাইপ ব্যাখ্যা করার জন্য ধন্যবাদ। এটা সত্যিই সাহায্য করে।
ছায়া অবধি

3
আমাদের তখন std::extentথেকে সি ++ 11 যা সংকলনের সময়।
এলএফ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.