এই প্রশ্নের পুরোপুরি কোডে উত্তর দেওয়া যাবে না। আপনি কিছুটা "সমতুল্য" কোড লিখতে সক্ষম হতে পারেন, তবে স্ট্যান্ডার্ডটি সেভাবে নির্দিষ্ট করা হয়নি।
উপায় যে এর বাইরে, এর মধ্যে ঝাঁপ দাও [expr.prim.lambda]
। প্রথম বিষয় লক্ষণীয় যে নির্মাতারা কেবল এতে উল্লেখ করেছেন [expr.prim.lambda.closure]/13
:
অবসান একটি সঙ্গে যুক্ত টাইপ ল্যামডা প্রকাশ যদি কোনো ডিফল্ট কনস্ট্রাকটর নেই তা ল্যামডা প্রকাশ টি ল্যামডা-ক্যাপচার এবং একটি খেলাপি ডিফল্ট কন্সট্রাকটর অন্যথায়। এটিতে একটি ডিফল্ট কপির কনস্ট্রাক্টর এবং একটি ডিফল্ট মুভ কনস্ট্রাক্টর ([শ্রেণি.কপি.ক্টোর]) রয়েছে। যদি এটি একটি মোছা কপি নিয়োগ অপারেটর রয়েছে ল্যামডা প্রকাশ টি ল্যামডা-ক্যাপচার এবং খেলাপি কপি এবং পদক্ষেপ নিয়োগ অপারেটার অন্যথায় ([class.copy.assign])। [ দ্রষ্টব্য: এই বিশেষ সদস্য ফাংশনগুলি যথারীতি সুস্পষ্টভাবে সংজ্ঞায়িত করা হয়েছে, এবং তাই মুছে ফেলা হিসাবে সংজ্ঞায়িত করা যেতে পারে। - শেষ নোট ]
সুতরাং ব্যাট থেকে সরাসরি, এটি পরিষ্কার হওয়া উচিত যে কন্সট্রাক্টরগুলি আনুষ্ঠানিকভাবে নয় কীভাবে ক্যাপচারিং অবজেক্টগুলি সংজ্ঞায়িত করা হয়। আপনি বেশ কাছাকাছি যেতে পারেন (সিপিনসাইটস.আইও উত্তর দেখুন), তবে বিশদগুলি পৃথক হয় (নোট 4 এর উত্তরটির কোডটি কীভাবে সংকলন করে না)।
এই কেস 1 টি আলোচনা করার জন্য প্রয়োজনীয় মূল স্ট্যান্ডার্ড ধারাগুলি:
[expr.prim.lambda.capture]/10
[...]
অনুলিপি দ্বারা বন্দী প্রতিটি সত্তার জন্য, নামবিহীন অ-স্থিতিশীল ডেটা সদস্য বন্ধের ধরণে ঘোষণা করা হয়। এই সদস্যদের ঘোষণার আদেশটি অনির্ধারিত। এই জাতীয় ডেটা সদস্যের প্রকারটি হ'ল রেফারেন্সযুক্ত ধরণ যদি সত্তা কোনও জিনিসের রেফারেন্স হয়, সত্তা কোনও ফাংশনের রেফারেন্স হলে রেফারেন্সড ফাংশন প্রকারের একটি লভ্যালু রেফারেন্স হয়, বা অন্যথায় সংশ্লিষ্ট ক্যাপচার সত্তার ধরণ। অনামী ইউনিয়নের কোনও সদস্য অনুলিপি দ্বারা ধরা পড়বে না।
[expr.prim.lambda.capture]/11
লাম্বডা-এক্সপ্রেশনটির যৌগিক বিবৃতিতে প্রতিটি আইডি-এক্সপ্রেশন যা অনুলিপি দ্বারা বন্দী কোনও সত্তার অদ্ভুত ব্যবহার হয় তা বন্ধের ধরণের সংশ্লিষ্ট নামবিহীন ডেটা সদস্যের অ্যাক্সেসে রূপান্তরিত হয়। [...]
[expr.prim.lambda.capture]/15
ল্যাম্বডা-এক্সপ্রেশনটি যখন মূল্যায়ন করা হয়, অনুলিপি দ্বারা ক্যাপচার করা সত্তাগুলি ফলাফলটি বন্ধ হয়ে যাওয়া অবজেক্টের প্রতিটি সম্পর্কিত নন-স্ট্যাটিক ডেটা সদস্যকে সরাসরি-আরম্ভ করতে ব্যবহার করা হয়, এবং আরআই-ক্যাপচারের সাথে সম্পর্কিত অ-স্থায়ী ডেটা সদস্যদের হিসাবে আরম্ভ করা হয় সংশ্লিষ্ট সূচক দ্বারা নির্দেশিত (যা কপি হতে পারে - বা সরাসরি-প্রাথমিককরণ)। [...]
আপনার কেস 1 এ এটি প্রয়োগ করুন:
কেস 1: মান অনুসারে ক্যাপচার / মান অনুসারে ডিফল্ট ক্যাপচার
int x = 6;
auto lambda = [x]() { std::cout << x << std::endl; };
এই ল্যাম্বদার ক্লোজার টাইপটির নামবিহীন অ-স্থিতিশীল ডেটা সদস্য থাকবে (যাক এটি কল করুন __x
) প্রকারের int
(যেহেতু x
কোনও রেফারেন্স বা কোনও ফাংশন নয়), এবং x
ল্যাম্বডা দেহের ভিতরে প্রবেশের প্রবেশাধিকারগুলিতে প্রবেশে রূপান্তরিত হয় __x
। আমরা যখন ল্যামডা অভিব্যক্তি নির্ণয় (অর্থাত যখন থেকে বরাদ্দ lambda
), আমরা ডাইরেক্ট-আরম্ভ __x
সঙ্গে x
।
সংক্ষেপে, কেবল একটি অনুলিপি স্থান নেয় । সমাপ্তির ধরণের নির্মাতারা এতে জড়িত নন এবং এটি "সাধারণ" সি ++ এ প্রকাশ করা সম্ভব নয় (নোট করুন যে বন্ধের ধরণটি একটি সামগ্রিক ধরণের নয়)।
রেফারেন্স ক্যাপচার জড়িত [expr.prim.lambda.capture]/12
:
কোনও সত্তা রেফারেন্স দ্বারা ক্যাপচার করা হয় যদি তা স্পষ্টভাবে বা স্পষ্টত ক্যাপচার করা হয় তবে অনুলিপি দ্বারা ক্যাপচারিত হয় না। রেফারেন্স দ্বারা বন্দী প্রতিষ্ঠানের জন্য অতিরিক্ত নামবিহীন অ-স্থিতিশীল ডেটা সদস্যদের ক্লোজার টাইপে ঘোষণা করা হয়েছে কিনা তা অনির্দিষ্ট ified [...]
রেফারেন্সগুলির রেফারেন্স ক্যাপচার সম্পর্কে আরও একটি অনুচ্ছেদ রয়েছে তবে আমরা এটি কোথাও করছি না।
সুতরাং, কেস 2 এর জন্য:
কেস 2: রেফারেন্স দ্বারা ক্যাপচার / রেফারেন্স দ্বারা ডিফল্ট ক্যাপচার
int x = 6;
auto lambda = [&x]() { std::cout << x << std::endl; };
কোনও সদস্যকে ক্লোজার টাইপের সাথে যুক্ত করা হয়েছে কিনা তা আমরা জানি না। x
ল্যাম্বডায় দেহে কেবল সরাসরি x
বাইরের দিকে উল্লেখ করা যেতে পারে । এটি নির্ধারণের জন্য সংকলকটির উপর নির্ভর করে এবং এটি মধ্যবর্তী ভাষার কিছু আকারে এটি করবে (যা সংকলক থেকে সংকলক থেকে পৃথক), সি ++ কোডের উত্স রূপান্তর নয়।
ইনিশ ক্যাপচারগুলি এখানে বিস্তারিত [expr.prim.lambda.capture]/6
:
একটি দীক্ষা-ক্যাপচারটি এমন আচরণ করে যেমন এটি ঘোষণা করে এবং স্পষ্টভাবে ফর্মটির একটি পরিবর্তনশীল ক্যাপচার করে auto init-capture ;
যার ঘোষিত অঞ্চলটি ল্যাম্বডা-এক্সপ্রেশনটির যৌগিক বিবৃতি, ব্যতীত:
- (.1.১) ক্যাপচারটি যদি অনুলিপি দ্বারা হয় (নীচে দেখুন), ক্যাপচারের জন্য ঘোষিত অ স্থিতিশীল ডেটা সদস্য এবং পরিবর্তনশীল একই পদার্থকে উল্লেখ করার জন্য দুটি ভিন্ন উপায় হিসাবে বিবেচিত হয়, যা অ স্থির তথ্যের আজীবন রয়েছে সদস্য, এবং কোনও অতিরিক্ত অনুলিপি এবং ধ্বংস সঞ্চালিত হয় না, এবং
- (.2.২) ক্যাপচারটি যদি রেফারেন্স অনুসারে হয় তবে ক্লোজার অবজেক্টের জীবনকাল শেষ হলে ভেরিয়েবলের জীবনকাল শেষ হয়।
দেওয়া হয়েছে, আসুন কেস 3 তাকান:
কেস 3: জড়িত ডিআইইন ক্যাপচার
auto lambda = [x = 33]() { std::cout << x << std::endl; };
যেমনটি বলা হয়েছে, এটিকে একটি পরিবর্তনশীল হিসাবে তৈরি করা হয়েছে auto x = 33;
এবং স্পষ্টভাবে অনুলিপি দ্বারা ক্যাপচার করা হয়েছে হিসাবে এটি কল্পনা করুন । এই পরিবর্তনশীল ল্যাম্বডা শরীরের মধ্যে কেবল "দৃশ্যমান"। পূর্বে উল্লিখিত হিসাবে [expr.prim.lambda.capture]/15
, __x
লম্বা এক্সপ্রেশন মূল্যায়নের পরে প্রদত্ত প্রারম্ভিক দ্বারা ক্লোজার টাইপের ( উত্তরোত্তর জন্য) সম্পর্কিত সদস্যের সূচনা হয়।
সন্দেহ এড়াতে: এর অর্থ এই নয় যে এখানে জিনিসগুলি দু'বার শুরু করা হয়েছে। auto x = 33;
একটি "যেন" সরল যেমনটি এর শব্দার্থবিদ্যা উত্তরাধিকারী, এবং বর্ণনা আরম্ভের সেই শব্দার্থবিদ্যা করার একটি পরিবর্তন হয়। কেবল একটি সূচনা ঘটে।
এটি কেস ৪ কেও অন্তর্ভুক্ত করে:
auto l = [p = std::move(unique_ptr_var)]() {
// do something with unique_ptr_var
};
__p = std::move(unique_ptr_var)
ল্যাম্বডা এক্সপ্রেশনটি যখন মূল্যায়ন করা হয় (অর্থাৎ যখন l
নির্দিষ্ট করা হয়) তখন ক্লোজার টাইপের সদস্যটি সূচনা করা হয় । থেকে অ্যাকসেস p
ল্যামডা শরীরে থেকে ব্যবহারের রুপান্তরিত হয় __p
।
টিএল; ডিআর: কেবলমাত্র সংখ্যক অনুলিপি / প্রারম্ভিককরণ / চালগুলি সম্পাদন করা হয় (যেমনটি আশা / আশা করা যায়)। আমি অনুমান যে lambdas হয় না একটি উৎস রূপান্তর পরিপ্রেক্ষিতে নিদিষ্ট (অন্যান্য অন্বিত চিনি অসদৃশ) ঠিক কারণ কনস্ট্রাকটর পরিপ্রেক্ষিতে কিছু প্রকাশ অতিরিক্ত অপারেশন অবশ্যম্ভাবী হবে।
আমি আশা করি এটি প্রশ্নের মধ্যে প্রকাশিত ভয়কে মীমাংসিত করবে :)