ভাল, আপনার কোড কাজ করে না। তবে এটি করে:
template<class F>
struct ycombinator {
F f;
template<class...Args>
auto operator()(Args&&...args){
return f(f, std::forward<Args>(args)...);
}
};
template<class F>
ycombinator(F) -> ycombinator<F>;
পরীক্ষার কোড:
ycombinator bob = {[x=0](auto&& self)mutable{
std::cout << ++x << "\n";
ycombinator ret = {self};
return ret;
}};
bob()()(); // prints 1 2 3
আপনার কোড উভয়ই ইউবি এবং দুর্বৃত্ত - কোনও ডায়াগনস্টিকের প্রয়োজন নেই। যা মজার; তবে উভয়ই স্বাধীনভাবে স্থির করা যায়।
প্রথমত, ইউবি:
auto it = [&](auto self) { // outer
return [&](auto b) { // inner
std::cout << (a + b) << std::endl;
return self(self);
};
};
it(it)(4)(5)(6);
এটি ইউবি কারণ বাইরের self
মান দ্বারা গ্রহণ করে, তারপরে অভ্যন্তরীণ self
রেফারেন্স দ্বারা ক্যাপচার করে, তারপরে outer
চলমান শেষের পরে এটি ফিরে আসতে এগিয়ে যায় । সুতরাং segfaulting অবশ্যই ঠিক আছে।
ঠিক করা:
[&](auto self) {
return [self,&a](auto b) {
std::cout << (a + b) << std::endl;
return self(self);
};
};
কোডটি অবরুদ্ধ। এটি দেখতে আমরা ল্যাম্বডাস প্রসারিত করতে পারি:
struct __outer_lambda__ {
template<class T>
auto operator()(T self) const {
struct __inner_lambda__ {
template<class B>
auto operator()(B b) const {
std::cout << (a + b) << std::endl;
return self(self);
}
int& a;
T self;
};
return __inner_lambda__{a, self};
}
int& a;
};
__outer_lambda__ it{a};
it(it);
এই তাত্ক্ষণিক __outer_lambda__::operator()<__outer_lambda__>
:
template<>
auto __outer_lambda__::operator()(__outer_lambda__ self) const {
struct __inner_lambda__ {
template<class B>
auto operator()(B b) const {
std::cout << (a + b) << std::endl;
return self(self);
}
int& a;
__outer_lambda__ self;
};
return __inner_lambda__{a, self};
}
int& a;
};
সুতরাং আমরা পরবর্তী রিটার্ন টাইপ নির্ধারণ করতে হবে __outer_lambda__::operator()
।
আমরা এটি লাইন লাইন দিয়ে যেতে। প্রথমে আমরা __inner_lambda__
টাইপ তৈরি করি :
struct __inner_lambda__ {
template<class B>
auto operator()(B b) const {
std::cout << (a + b) << std::endl;
return self(self);
}
int& a;
__outer_lambda__ self;
};
এখন, সেখানে দেখুন - এর রিটার্ন টাইপ হয় self(self)
, বা __outer_lambda__(__outer_lambda__ const&)
। তবে আমরা রিটার্নের ধরণটি কমাতে চেষ্টা করার মাঝখানে আছি __outer_lambda__::operator()(__outer_lambda__)
।
আপনাকে এটি করার অনুমতি নেই।
প্রকৃতপক্ষে রিটার্নের ধরণটি রিটার্নের ধরণের __outer_lambda__::operator()(__outer_lambda__)
উপর নির্ভর করে না, রিটার্নের ধরণের সময় __inner_lambda__::operator()(int)
সি ++ কেটে নেওয়ার সময় যত্ন নেই; এটি কেবল লাইন দ্বারা কোড লাইনটি পরীক্ষা করে।
এবং self(self)
এটি হ্রাস করার আগে ব্যবহার করা হয়। আমি গঠিত প্রোগ্রাম।
আমরা এটি self(self)
পরে লুকিয়ে রেখে প্যাচ করতে পারি :
template<class A, class B>
struct second_type_helper { using result=B; };
template<class A, class B>
using second_type = typename second_type_helper<A,B>::result;
int main(int argc, char* argv[]) {
int a = 5;
auto it = [&](auto self) {
return [self,&a](auto b) {
std::cout << (a + b) << std::endl;
return self(second_type<decltype(b), decltype(self)&>(self) );
};
};
it(it)(4)(6)(42)(77)(999);
}
এবং এখন কোডটি সঠিক এবং সংকলিত। তবে আমি মনে করি এটি কিছুটা হ্যাক; শুধু ycombinator ব্যবহার করুন।