স্ট্যান্ড :: ক্ষয় কী এবং কখন ব্যবহার করা উচিত?


185

অস্তিত্বের কারণ কী std::decay? কোন পরিস্থিতিতে std::decayদরকারী?


3
এটি স্ট্যান্ডার্ড লাইব্রেরিতে যেমন ব্যবহৃত হয় যখন কোনও থ্রেডে আর্গুমেন্টগুলি পাস করার সময়। এগুলি মান অনুসারে সংরক্ষণ করা দরকার , সুতরাং আপনি উদাহরণস্বরূপ অ্যারেগুলি সঞ্চয় করতে পারবেন না। পরিবর্তে, একটি পয়েন্টার সংরক্ষণ করা হয় এবং তাই। এটি একটি মেটাফংশন যা ফাংশন প্যারামিটার ধরণের সমন্বয়গুলি নকল করে।
ডায়প

3
decay_t<decltype(...)>কি autoহ্রাস হবে তা দেখতে একটি দুর্দান্ত সমন্বয় ।
মার্ক গ্লিস

58
তেজস্ক্রিয় ভেরিয়েবল? :)
saiarcot895

7
std :: ক্ষয় () তিনটি জিনিস করতে পারে। 1 এটি টির একটি অ্যারে টি * তে রূপান্তর করতে সক্ষম; 2. এটি সিভি কোয়ালিফায়ার এবং রেফারেন্স অপসারণ করতে পারে; ৩. এটি ফাংশন টি-তে * রূপান্তর করে। যেমন ক্ষয় (অকার্যকর (চর)) -> অকার্যকর (*) (চর)। উত্তরে কেউ তৃতীয় ব্যবহারের কথা উল্লেখ করেছে বলে মনে হচ্ছে।
r0ng

1
ধার্মিকতার জন্য ধন্যবাদ আমাদের কাছে এখনও সি ++ তে কোয়ার্ক নেই
10-15

উত্তর:


192

<জোক> এটি স্পষ্টতই তেজস্ক্রিয় std::atomicধরণের ক্ষয়র জন্য অ-তেজস্ক্রিয় উপাদানগুলিতে ব্যবহৃত হয় </ </ জোক>

এন 2609 প্রস্তাবিত কাগজ std::decay। কাগজটি ব্যাখ্যা করেছে:

সোজা কথায়, decay<T>::typeপরিচয় টাইপ-ট্রান্সফর্মেশনটি হ'ল টি যদি অ্যারে টাইপ বা কোনও ফাংশনের ধরণের রেফারেন্স হয়। এই ক্ষেত্রে decay<T>::typeযথাক্রমে একটি ফাংশনে একটি পয়েন্টার বা পয়েন্টার উপার্জন করে।

প্রেরণাদায়ী উদাহরণটি সি ++ 03 std::make_pair:

template <class T1, class T2> 
inline pair<T1,T2> make_pair(T1 x, T2 y)
{ 
    return pair<T1,T2>(x, y); 
}

যা স্ট্রিং আক্ষরিক কাজ করতে মান দ্বারা তার পরামিতি গ্রহণ করেছে:

std::pair<std::string, int> p = make_pair("foo", 0);

যদি রেফারেন্স অনুসারে এটি এর পরামিতিগুলি স্বীকার করে, তবে T1একটি অ্যারে টাইপ হিসাবে ছাড় করা হবে, এবং তারপরে একটি নির্মাণ pair<T1, T2>করা খারাপ-গঠন হবে।

তবে স্পষ্টতই এটি উল্লেখযোগ্য অদক্ষতার দিকে পরিচালিত করে। অতএব, decayপাস-বাই-মানটি ঘটে যখন রূপান্তরগুলির সেটটি প্রয়োগ করার জন্য প্রয়োজনীয়তাটি আপনাকে রেফারেন্সের মাধ্যমে পরামিতিগুলি গ্রহণের দক্ষতা পেতে সক্ষম করে, তবে আপনার কোডটির স্ট্রিং লিটারেলগুলির সাথে কাজ করার জন্য প্রয়োজনীয় ধরণের রূপান্তরগুলি পেতে, অ্যারের ধরণ, ফাংশনের ধরণ এবং এর মতো:

template <class T1, class T2> 
inline pair< typename decay<T1>::type, typename decay<T2>::type > 
make_pair(T1&& x, T2&& y)
{ 
    return pair< typename decay<T1>::type, 
                 typename decay<T2>::type >(std::forward<T1>(x), 
                                            std::forward<T2>(y)); 
}

দ্রষ্টব্য: এটি আসল সি ++ 11 make_pairবাস্তবায়ন নয় - সি ++ 11 make_pairটিও সরিয়ে দেয় std::reference_wrapper


"টি 1 অ্যারের ধরণের হিসাবে বিয়োগ করা হবে, এবং তারপরে <টি 1, টি 2> একটি জোড় তৈরি করা হবে না।" এখানে কি সমস্যা?
ক্যামিনো 25'16

6
আমি এটি পেয়েছি, এইভাবে আমরা পেয়ারটি পেয়ে যাব <চর [4], ইনটি> যা কেবল 4 টি অক্ষরের সাথে স্ট্রিং গ্রহণ করতে পারে
ক্যামিনো

@ ক্যামিনো আমি এটি পেলাম না, আপনি কি বলছেন যে এইচটিডি ছাড়াই: ক্ষয় ছাড়া জোড়ার প্রথম অংশটি চার পয়েন্টের জন্য চার বাইটের জন্য চার পয়েন্টের পরিবর্তে চারটি বাইট দখল করবে? স্ট্যান্ড :: ফরোয়ার্ড কি তাই করে? এটি অ্যারে থেকে পয়েন্টারের ক্ষয় থেকে থামছে?
জেব্রাফিশ

3
@ জেব্রাফিশ- এটি অ্যারে ক্ষয়। উদাহরণস্বরূপ: টেমপ্লেট <typename T> void f (T &); চ ( "ABC"); টি চর (এবং) [4], তবে টেমপ্লেট <টাইপনেম টি> শূন্য চ (টি); চ ( "ABC"); টি হল চর *; আপনি এখানে একটি ব্যাখ্যাও পেতে পারেন: stackoverflow.com/questions/7797839/…
ক্যামিনো

68

টেমপ্লেট ফাংশনগুলির সাথে কাজ করার সময় যা কোনও টেম্পলেট ধরণের পরামিতি নেয়, আপনার প্রায়শই সর্বজনীন পরামিতি থাকে। ইউনিভার্সাল প্যারামিটারগুলি প্রায়শই এক ধরণের বা অন্যরকমের উল্লেখ। তারাও কনস্ট-অস্থির যোগ্য। এই হিসাবে, বেশিরভাগ ধরণের বৈশিষ্ট্যগুলি আপনি যেমন আশা করেছিলেন তেমন সেগুলি নিয়ে কাজ করে না:

template<class T>
void func(T&& param) {
    if (std::is_same<T,int>::value) 
        std::cout << "param is an int\n";
    else 
        std::cout << "param is not an int\n";
}

int main() {
    int three = 3;
    func(three);  //prints "param is not an int"!!!!
}

http://coliru.stacked-crooked.com/a/24476e60bd906bed

সমাধানটি এখানে ব্যবহার করুন std::decay:

template<class T>
void func(T&& param) {
    if (std::is_same<typename std::decay<T>::type,int>::value) 
        std::cout << "param is an int\n";
    else 
        std::cout << "param is not an int\n";
}

http://coliru.stacked-crooked.com/a/8cbd0119a28a18bd


14
আমি এতে খুশি নই। decayখুব আক্রমণাত্মক, উদাহরণস্বরূপ যদি অ্যারেতে কোনও রেফারেন্স প্রয়োগ করা হয় তবে এটি একটি পয়েন্টার দেয়। এটি সাধারণত এই জাতীয় রূপক আইএমএইচওর জন্য খুব আক্রমণাত্মক।
ডায়াপ

@ ডিআইপি, এরপরে কম "আক্রমণাত্মক" কী? বিকল্প কি কি?
সার্জ রোগাচ

5
@ সার্জারোগ্যাচ "সার্বজনীন পরামিতি" / সার্বজনীন রেফারেন্স / ফরোয়ার্ডিং রেফারেন্সের ক্ষেত্রে আমি কেবলমাত্র remove_const_t< remove_reference_t<T> >একটি কাস্টম মেটাফ্যাঙ্কশনে আবৃত ছিলাম ।
ডায়প

1
কোথায় পরম ব্যবহার করা হচ্ছে? এটি
মজাদার

2
@ সাভ্রাম: এই কোডের টুকরো: এটি নয়। আমরা কেবল প্রকারটি পরীক্ষা করছি, মানটি নয়। আমরা যদি প্যারামিটারের নামটি সরিয়ে ফেলি তবে আরও ভাল না হলে সবকিছু ঠিকঠাক কাজ করা উচিত।
মাকিং হাঁস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.