আমি সম্প্রতি একটি রেডডিট আলোচনা অনুসরণ করেছি যা সংকলকগুলিতে std::visitঅপ্টিমাইজেশনের একটি দুর্দান্ত তুলনা করতে পারে । আমি নিম্নলিখিতটি লক্ষ্য করেছি: https://godbolt.org/z/D2Q5ED
সমস্ত ধরণের কিছু শর্ত পূরণ করার সময় GCC9 এবং Clang9 উভয়ই (আমি অনুমান করি যে তারা একই স্টাডলিব ভাগ করে নিচ্ছে) মূল্যহীন ব্যতিক্রম পরীক্ষা করার জন্য কোড তৈরি করে না। এটি উন্নত কোডজেনের দিকে পরিচালিত করে, তাই আমি এমএসভিসি এসটিএলে একটি সমস্যা উত্থাপন করেছি এবং এই কোড সহ উপস্থাপিত হয়েছিল:
template <class T>
struct valueless_hack {
struct tag {};
operator T() const { throw tag{}; }
};
template<class First, class... Rest>
void make_valueless(std::variant<First, Rest...>& v) {
try { v.emplace<0>(valueless_hack<First>()); }
catch(typename valueless_hack<First>::tag const&) {}
}
দাবি ছিল, যে এই কোন বৈকল্পিক মূল্যহীন করে তোলে, এবং পড়া ডকু এটি করা উচিত:
প্রথমে বর্তমানে বিদ্যমান মান (যদি থাকে তবে) নষ্ট করে দেয়। তারপরে অন্তর্ভুক্ত মানটিকে সরাসরি-সূচনা করে যেমন
T_Iআর্গুমেন্টের সাথে টাইপের মান নির্মান করেstd::forward<Args>(args)....যদি একটি ব্যতিক্রম ছুঁড়ে দেওয়া হয় তবে*thisমূল্যহীন_বি_অপত্তি হতে পারে।
যা আমি বুঝতে পারি না: কেন এটি "মে" হিসাবে বর্ণিত হয়েছে? পুরো অপারেশনটি ছুড়ে মারলে কি পুরানো অবস্থায় থাকা আইনসম্মত? কারণ এটিই জিসিসি করে:
// For suitably-small, trivially copyable types we can create temporaries
// on the stack and then memcpy them into place.
template<typename _Tp>
struct _Never_valueless_alt
: __and_<bool_constant<sizeof(_Tp) <= 256>, is_trivially_copyable<_Tp>>
{ };
এবং পরে এটি (শর্তাধীন) এর মতো কিছু করে:
T tmp = forward(args...);
reset();
construct(tmp);
// Or
variant tmp(inplace_index<I>, forward(args...));
*this = move(tmp);
সুতরাং মূলত এটি একটি অস্থায়ী তৈরি করে, এবং যদি এটি অনুলিপিগুলি / সফল স্থানে স্থানান্তরিত করে।
আইএমও এটি নথির বিবরণ অনুসারে "প্রথমে বিদ্যমান বিদ্যমান মানটি ধ্বংস করে" লঙ্ঘন। আমি যেমন স্ট্যান্ডার্ডটি পড়ি, তারপরে v.emplace(...)বৈকল্পের বর্তমান মানটি সর্বদা নষ্ট হয়ে যায় এবং নতুন প্রকারটি হয় সেট প্রকার বা মূল্যহীন।
আমি বুঝতে পারি যে শর্তটি is_trivially_copyableপর্যবেক্ষণযোগ্য ডেস্ট্রাক্টর রয়েছে এমন সমস্ত ধরণের বাদ দেয়। সুতরাং এটি যদিও হিসাবেও হতে পারে: "যেমন-যদি বৈকল্পিকটি পুরানো মানের সাথে পুনরায় পুনঃনির্মাণ করা হয়" বা তেমনি। তবে বৈকল্পিকের অবস্থা একটি পর্যবেক্ষণযোগ্য প্রভাব। তাহলে স্ট্যান্ডার্ডটি কি প্রকৃতপক্ষে অনুমতি দেয় emplaceযা বর্তমান মানটি পরিবর্তন করে না?
একটি স্ট্যান্ডার্ড উক্তির জবাবে সম্পাদনা করুন:
তারপরে থাকা মানটি এমনভাবে শুরু করে যেন আর্গুমেন্টের সাহায্যে টিআই টাইপের মান প্রত্যক্ষ-অ-তালিকা-সূচনা করে
std::forward<Args>(args)...।
কি T tmp {std::forward<Args>(args)...}; this->value = std::move(tmp);সত্যিই উপরোক্ত একটি বৈধ বাস্তবায়ন হিসাবে গণনা? এটাই কি "যেন" বলতে বোঝায়?
might/mayশব্দটি দ্বারা খুব বিভ্রান্ত হয়েছি কারণ মানটি বিকল্পটি কী তা বলে না।