c++ যখন ভিত্ত শ্রেণিটি না হয় তখন কেন উত্পন্ন শ্রেণীর পদক্ষেপটি গঠনমূলক?




c++11 language-lawyer (2)

std::is_move_constructible এর আচরণ

এটি std::is_move_constructible প্রত্যাশিত আচরণ:

std::is_move_constructible ছাড়াই প্রকার, তবে একটি অনুলিপি নির্মাণকারী যা std::is_move_constructible const T& আর্গুমেন্ট গ্রহণ করে, std::is_move_constructible সন্তুষ্ট করে।

যার অর্থ একটি অনুলিপি নির্মাণকারীর সাথে এখনও মূল্যের রেফারেন্স টিএন্ডএন্ড থেকে T নির্মাণ সম্ভব। এবং Foo<Bar> এর একটি সুস্পষ্টভাবে ঘোষিত অনুলিপি নির্মাণকারী রয়েছে

2. Foo<Bar> এর সুস্পষ্টভাবে ঘোষিত মুভ কনস্ট্রাক্টর

বেস ক্লাসটি নন-মুভ-কনস্ট্রাকটেবল হওয়া সত্ত্বেও সংকলক মুভি কনস্ট্রাক্টর কেন জেনারেট করে?

আসলে, Foo<Bar> মুভ কনস্ট্রাক্টর deleted হিসাবে সংজ্ঞায়িত করা হয়েছে তবে নোট করুন যে মুছে ফেলা সুস্পষ্টভাবে ঘোষিত মুভ কনস্ট্রাক্টর ওভারলোড রেজোলিউশন দ্বারা উপেক্ষা করা হবে।

ক্লাস T জন্য সুস্পষ্টভাবে ঘোষিত বা খেলাপী মুভ কনস্ট্রাক্টরকে নীচের যে কোনওটিতে মুছে ফেলা হিসাবে সংজ্ঞায়িত করা হয়েছে সত্য:

...
T has direct or virtual base class that cannot be moved (has deleted, inaccessible, or ambiguous move constructors); 
...

মুছে ফেলা সুস্পষ্টভাবে ঘোষিত মুভ কনস্ট্রাক্টরকে ওভারলোড রেজোলিউশন দ্বারা উপেক্ষা করা হয় (অন্যথায় এটি মূল্য থেকে কপি-ইনিশিয়ালাইজেশন আটকাতে পারে)।

৩. Bar এবং Foo<Bar> মধ্যে আলাদা আচরণ

নোট করুন যে Bar মুভ কনস্ট্রাক্টর স্পষ্টভাবে deleted হিসাবে ঘোষিত হয়েছে এবং Foo<Bar> মুভ কনস্ট্রাক্টর স্পষ্টভাবে ঘোষিত হয়েছে এবং deleted হিসাবে সংজ্ঞায়িত করা হয়েছে। মুল বক্তব্যটি হ'ল মুছে ফেলা সুস্পষ্টভাবে ঘোষিত মুভ কনস্ট্রাক্টরকে ওভারলোড রেজোলিউশন দ্বারা উপেক্ষা করা হয় , যা তার অনুলিপি কনস্ট্রাক্টর দিয়ে Foo<Bar> কনস্ট্রাক্টর স্থানান্তরিত করে তোলে। তবে স্পষ্টরূপে মুছে ফেলা মুভ কনস্ট্রাক্টর ওভারলোড রেজোলিউশনে অংশ নেবে, অর্থাৎ কনস্ট্রাক্টর Bar সরানোর চেষ্টা করার পরে মুছে ফেলা মুভ কনস্ট্রাক্টর নির্বাচন করা হবে, তারপরে প্রোগ্রামটি খারাপ-গঠনযুক্ত।

সে কারণেই Foo<Bar> তবে Bar তা নয়।

মান সম্পর্কে এই সম্পর্কে একটি স্পষ্ট বিবৃতি আছে। .8 12.8 / 11 শ্রেণি অবজেক্টগুলি অনুলিপি করা এবং চালনা করা হচ্ছে [শ্রেণি.কপি]

মুছে ফেলা হিসাবে সংজ্ঞায়িত একটি ডিফল্ট মুভ কনস্ট্রাক্টর ওভারলোড রেজোলিউশন ([over.match], [over.over]) দ্বারা উপেক্ষা করা হয়। [দ্রষ্টব্য: মুছে ফেলা মুভ কনস্ট্রাক্টর অন্যথায় কোনও মুদ্রার থেকে আরম্ভের সাথে হস্তক্ষেপ করবে যা এর পরিবর্তে অনুলিপি অনুলিপি ব্যবহার করতে পারে। - শেষ নোট]

নিম্নলিখিত উদাহরণ বিবেচনা করুন:

#include <iostream>
#include <string>
#include <utility>

template <typename Base> struct Foo : public Base {
    using Base::Base;
};

struct Bar {
    Bar(const Bar&) { }
    Bar(Bar&&) = delete;
};

int main() {
    std::cout << std::is_move_constructible<Bar>::value << std::endl; // NO
    std::cout << std::is_move_constructible<Foo<Bar>>::value << std::endl; // YES. Why?!
}

বেস ক্লাসটি নন-মুভ-কনস্ট্রাকটেবল হওয়া সত্ত্বেও সংকলক কেন একটি মুভ কনস্ট্রাক্টর তৈরি করে?

এটি কি স্ট্যান্ডার্ডে আছে বা এটি একটি সংকলক বাগ রয়েছে? বেস থেকে উত্পন্ন শ্রেণীর দিকে নির্মাণের কাজটি কি "পুরোপুরি প্রচার" করা সম্ভব?


কারণ:

মুছে ফেলা হিসাবে সংজ্ঞায়িত একটি ডিফল্ট মুভ কনস্ট্রাক্টর ওভারলোড রেজোলিউশন দ্বারা উপেক্ষা করা হয়।

([Class.copy] / 11)

Bar মুভ কনস্ট্রাক্টর স্পষ্টভাবে মুছে ফেলা হয়েছে , সুতরাং Bar সরানো যায় না। তবে Foo<Bar> এর পদক্ষেপের নির্মাতা স্পষ্টভাবে ডিফল্ট হিসাবে ঘোষণা হওয়ার পরে মুছে ফেলা হয়েছে , Bar সদস্যকে সরানো যায় না এই কারণে। সুতরাং Foo<Bar> এর অনুলিপি নির্মাণকারী ব্যবহার করে সরানো যেতে পারে।

সম্পাদনা: আমি গুরুত্বপূর্ণ বিষয়টিও উল্লেখ করতে ভুলে গিয়েছিলাম যে উত্তরাধিকারসূতী কনস্ট্রাক্টর ঘোষণা যেমন using Base::Base ডিফল্ট, অনুলিপি বা কনস্ট্রাক্টর মুভ করে না, সুতরাং সে কারণেই Foo<Bar> স্পষ্টভাবে মুছে ফেলা হয়নি এমন কনস্ট্রাক্টরের উত্তরাধিকার সূত্রে প্রাপ্ত Bar থেকে





move-constructor