c++ - সি++ বই




সি++ ফ্যাক্টর এবং তাদের ব্যবহার কি? (10)

আমি C ++ এ ফ্যাক্টর সম্পর্কে অনেক কিছু শুনছি। কেউ কি আমার সম্পর্কে একটি পরিদর্শন দিতে পারে এবং তারা কোন ক্ষেত্রে উপকারী হবে?


অন্যরা যেমন উল্লেখ করেছেন, একটি ফ্যান্টक्टर এমন একটি বস্তু যা একটি ফাংশন হিসাবে কাজ করে, অর্থাৎ এটি ফাংশন কল অপারেটরকে ওভারলোড করে।

ফাংশ্টগুলি সাধারণত STL অ্যালগরিদম ব্যবহার করা হয়। তারা কার্যকরী কারণ তারা ফাংশন কলগুলির আগে এবং এর মধ্যে রাষ্ট্রকে ধরে রাখতে পারে, যেমন ক্রিয়ামূলক ভাষাগুলিতে বন্ধ। উদাহরণস্বরূপ, আপনি একটি MultiplyBy ফাংশক সংজ্ঞায়িত করতে পারেন যা নির্দিষ্ট পরিমাণের দ্বারা তার যুক্তিকে গুণিত করে:

class MultiplyBy {
private:
    int factor;

public:
    MultiplyBy(int x) : factor(x) {
    }

    int operator () (int other) const {
        return factor * other;
    }
};

তারপর আপনি একটি MultiplyBy অবজেক্টটি একটি অ্যালগরিদম যেমন স্টেড :: ট্রান্সফর্ম পাস করতে পারেন:

int array[5] = {1, 2, 3, 4, 5};
std::transform(array, array + 5, array, MultiplyBy(3));
// Now, array is {3, 6, 9, 12, 15}

একটি ফাংশন একটি পয়েন্টার উপর একটি ফ্যান্টরটার আরেকটি সুবিধা হল যে কল আরো ক্ষেত্রে সংশোধন করা যেতে পারে। যদি আপনি transform করার জন্য একটি ফাংশন পয়েন্টার পাস করেন, তবে সেই কলটি ইনলাইন না হওয়া পর্যন্ত এবং কম্পাইলারটি জানেন যে আপনি সর্বদা একই ফাংশনটি পাস করেন, এটি পয়েন্টারের মাধ্যমে কলটিতে ইনলাইন করতে পারে না।


আমাদের মধ্যে নতুন মতামত জন্য: একটু গবেষণা পরে আমি figured কোড জাফ পোস্ট কি।

একটি মজাদার একটি বর্গ বা গঠন বস্তু যা একটি ফাংশনের মতো "কল করা" হতে পারে। এই () operator overloading দ্বারা সম্ভব করা হয়। () operator (নিশ্চিত নয় যে এটি কী বলে) কোনও আর্গুমেন্ট নিতে পারে। অন্য অপারেটররা শুধুমাত্র দুটি গ্রহণ করে, + operator কেবল দুটি মান (অপারেটরের প্রতিটি পাশে একটি) নিতে পারে এবং এটির জন্য যে পরিমাণ মানটি আপনি ওভারলোড করেছেন তা ফেরত পাঠান। আপনি একটি () operator ভিতরে কোনও আর্গুমেন্ট মাপসই করতে পারেন যা এটি তার নমনীয়তা দেয়।

প্রথমে একটি ফ্যান্টর্ট তৈরি করতে আপনার ক্লাস তৈরি করুন। তারপরে আপনি আপনার পছন্দ এবং পছন্দের প্যারামিটার সহ ক্লাসে একটি কন্সট্রকটর তৈরি করেন। এটি একটি সূচনাকারী তালিকার দ্বারা একই বিবৃতি অনুসরণ করা হয় (যা একটি একক কোলন অপারেটর ব্যবহার করে, যা আমি নতুন ছিলাম) যা গঠনকারীর পূর্বে ঘোষিত পরামিতির সাথে শ্রেণির সদস্য বস্তুর গঠন করে। তারপর () operator ওভারলোড করা হয়। অবশেষে আপনি আপনার তৈরি ক্লাস বা কাঠামোর ব্যক্তিগত বস্তু ঘোষণা।

আমার কোড (আমি jalf এর পরিবর্তনশীল নাম বিভ্রান্তিকর খুঁজে পাওয়া যায় নি)

class myFunctor
{ 
    public:
        /* myFunctor is the constructor. parameterVar is the parameter passed to
           the constructor. : is the initializer list operator. myObject is the
           private member object of the myFunctor class. parameterVar is passed
           to the () operator which takes it and adds it to myObject in the
           overloaded () operator function. */
        myFunctor (int parameterVar) : myObject( parameterVar ) {}

        /* the "operator" word is a keyword which indicates this function is an 
           overloaded operator function. The () following this just tells the
           compiler that () is the operator being overloaded. Following that is
           the parameter for the overloaded operator. This parameter is actually
           the argument "parameterVar" passed by the constructor we just wrote.
           The last part of this statement is the overloaded operators body
           which adds the parameter passed to the member object. */
        int operator() (int myArgument) { return myObject + myArgument; }

    private: 
        int myObject; //Our private member object.
}; 

এই যে কোনো ভুল বা শুধু ভুল ভুল আমাকে সংশোধন করতে মুক্ত মনে হয়!


একটি ফাংশন একটি বস্তু যা একটি ফাংশন মত কাজ করে। মূলত, একটি শ্রেণী যা operator() সংজ্ঞায়িত করে operator()

class MyFunctor
{
   public:
     int operator()(int x) { return x * 2;}
}

MyFunctor doubler;
int x = doubler(5);

বাস্তব সুবিধা একটি ফ্যান্টর রাষ্ট্র রাখা যাবে।

class Matcher
{
   int target;
   public:
     Matcher(int m) : target(m) {}
     bool operator()(int x) { return x == target;}
}

Matcher Is5(5);

if (Is5(n))    // same as if (n == 5)
{ ....}

একটি ফাংশন মধ্যে একটি স্থানীয় ফাংশন সংজ্ঞায়িত অনুকরণ করতে ফাংশন ব্যবহার করা যেতে পারে। question এবং another

কিন্তু একটি স্থানীয় ফ্যান্টর বাইরে স্বয়ংক্রিয় ভেরিয়েবল অ্যাক্সেস করতে পারবেন না। Lambda (সি ++ 11) ফাংশন একটি ভাল সমাধান।


একটি মজাদার একটি উচ্চ-ক্রম ফাংশন যা প্যারামেট্রিজড (যেমন templated) ধরনের একটি ফাংশন প্রযোজ্য। এটি map উচ্চ ক্রম ফাংশন একটি সাধারণীকরণ। উদাহরণস্বরূপ, আমরা std::vector জন্য একটি ফ্যান্টक्टर সংজ্ঞায়িত করতে পারি:

template<class F, class T, class U=decltype(std::declval<F>()(std::declval<T>()))>
std::vector<U> fmap(F f, const std::vector<T>& vec)
{
    std::vector<U> result;
    std::transform(vec.begin(), vec.end(), std::back_inserter(result), f);
    return result;
}

এই ফাংশনটি std::vector<T> নেয় এবং ফাংশন F প্রদান করে std::vector<U> প্রদান করে যা একটি T নেয় এবং একটি U । একটি ফ্যান্টর কন্টেইনার প্রকারের উপর সংজ্ঞায়িত করতে হবে না, এটি std::shared_ptr সহ কোনও templated টাইপের জন্য সংজ্ঞায়িত করা যেতে পারে:

template<class F, class T, class U=decltype(std::declval<F>()(std::declval<T>()))>
std::shared_ptr<U> fmap(F f, const std::shared_ptr<T>& p)
{
    if (p == nullptr) return nullptr;
    else return std::shared_ptr<U>(new U(f(*p)));
}

একটি সহজ উদাহরণ যা হ'ল টাইপটিকে double রূপান্তরিত করে:

double to_double(int x)
{
    return x;
}

std::shared_ptr<int> i(new int(3));
std::shared_ptr<double> d = fmap(to_double, i);

std::vector<int> is = { 1, 2, 3 };
std::vector<double> ds = fmap(to_double, is);

ফ্যাক্টর অনুসরণ করা উচিত যে দুটি আইন আছে। প্রথমটি পরিচয় আইন, যা বলে যে যদি ফ্যান্টরকে পরিচয় ফাংশন দেওয়া হয় তবে এটি পরিচয় ফাংশনটিকে টাইপের ক্ষেত্রে প্রয়োগ করা একই রকম হওয়া উচিত, যা fmap(identity, x) identity(x) হিসাবে একই হওয়া উচিত identity(x) :

struct identity_f
{
    template<class T>
    T operator()(T x) const
    {
        return x;
    }
};
identity_f identity = {};

std::vector<int> is = { 1, 2, 3 };
// These two statements should be equivalent.
// is1 should equal is2
std::vector<int> is1 = fmap(identity, is);
std::vector<int> is2 = identity(is);

পরবর্তী আইনটি গঠন আইন, যা বলে যে যদি ফ্যান্টর্টকে দুটি ফাংশন গঠন করা হয় তবে এটি প্রথম ফাংশনের জন্য ফাংশ্ট প্রয়োগ করার সাথে সাথে দ্বিতীয় ফাংশনের জন্য একই রকম হওয়া উচিত। সুতরাং, fmap(std::bind(f, std::bind(g, _1)), x) fmap(f, fmap(g, x)) :

double to_double(int x)
{
    return x;
}

struct foo
{
    double x;
};

foo to_foo(double x)
{
    foo r;
    r.x = x;
    return r;
}

std::vector<int> is = { 1, 2, 3 };
// These two statements should be equivalent.
// is1 should equal is2
std::vector<foo> is1 = fmap(std::bind(to_foo, std::bind(to_double, _1)), is);
std::vector<foo> is2 = fmap(to_foo, fmap(to_double, is));

এখানে একটি প্রকৃত পরিস্থিতি যেখানে আমার সমস্যার সমাধান করার জন্য একটি ফাংশ্ট ব্যবহার করতে বাধ্য করা হয়েছিল:

আমি ফাংশন একটি সেট আছে (বলুন, তাদের 20), এবং তারা সব অভিন্ন, প্রতিটি ছাড়া 3 নির্দিষ্ট স্পট মধ্যে একটি ভিন্ন নির্দিষ্ট ফাংশন কল।

এটি অবিশ্বাস্য বর্জ্য, এবং কোড অনুলিপি। সাধারণত আমি শুধু একটি ফাংশন পয়েন্টার মধ্যে পাস, এবং শুধু 3 দাগ যে কল। (তাই কোডটি কেবল একবারই প্রদর্শিত হবে, পরিবর্তে ২0 বার।)

কিন্তু তারপর আমি বুঝতে পারলাম, প্রতিটি ক্ষেত্রে, নির্দিষ্ট ফাংশনটির জন্য একটি সম্পূর্ণ ভিন্ন প্যারামিটার প্রোফাইল প্রয়োজন! কখনও কখনও 2 পরামিতি, কখনও কখনও 5 পরামিতি, ইত্যাদি।

আরেকটি সমাধান বেস বর্গ থাকতে হবে, যেখানে নির্দিষ্ট ফাংশন একটি প্রাপ্ত শ্রেণীর মধ্যে একটি overridden পদ্ধতি। কিন্তু আমি সত্যিই এই সমস্ত অন্তর্নির্মিত নির্মাণ করতে চাই, তাই আমি একটি ফাংশন পয়েন্টার পাস করতে পারেন ????

সমাধান: তাই আমি যা করেছি, আমি একটি রপার ক্লাস (একটি "ফ্যাক্টর") তৈরি করেছি যা আমাকে বলা যেকোনো ফাংশন কল করতে সক্ষম। আমি এটি অগ্রিম সেট (তার পরামিতি সহ, ইত্যাদি) এবং তারপর আমি এটি একটি ফাংশন পয়েন্টার পরিবর্তে পাস। এখন কল করা কোডটি কীভাবে ঘটছে তা জানার পরে ফাংশ্টটিকে ট্রিগার করতে পারে। এটি এমনকি একাধিকবার কল করতে পারে (আমি এটি 3 বার কল করতে চাই।)

এটিই - একটি বাস্তব উদাহরণ যেখানে একটি ফাংশনটি সুস্পষ্ট ও সহজ সমাধান হিসাবে পরিণত হয়, যা আমাকে ২0 টি ফাংশন থেকে কোডের সদৃশতা কমিয়ে দেয়।


কিছু GUI বোতামটি প্রকৃত C ++ ফাংশন বা পদ্ধতিতে সংযোগ করার জন্য gtkmm এ ফাংশ্টগুলি ব্যবহার করা হয়।

আপনি যদি আপনার অ্যাপ্লিকেশনটি multithreaded করতে pthread লাইব্রেরি ব্যবহার করেন, ফাংশ্টরা আপনাকে সাহায্য করতে পারে।
থ্রেড শুরু করার জন্য, pthread_create(..) আর্গুমেন্টগুলির মধ্যে একটি হল ফাংশন পয়েন্টারটি নিজের থ্রেডে কার্যকর করা।
কিন্তু একটি অসুবিধা আছে। এই পয়েন্টার একটি পদ্ধতিতে পয়েন্টার হতে পারে না, যদি না এটি একটি স্ট্যাটিক পদ্ধতি না হয় , অথবা যদি না আপনি class::method মতো তার শ্রেণী উল্লেখ না করেন । এবং অন্য জিনিস, আপনার পদ্ধতির ইন্টারফেস শুধুমাত্র হতে পারে:

void* method(void* something)

সুতরাং আপনি (কিছুটা সহজ ভাবে) চালাতে পারবেন না, অতিরিক্ত কিছু না করে থ্রেডে আপনার ক্লাসের পদ্ধতিগুলি।

C ++ তে থ্রেডগুলির সাথে ডিল করার খুব ভাল উপায়, আপনার নিজস্ব Thread বর্গ তৈরি করছে। যদি আপনি MyClass ক্লাস থেকে পদ্ধতি চালাতে চান তবে আমি যা করেছি তা MyClass সেই পদ্ধতিগুলিকে রূপান্তর করুন।

এছাড়াও, Thread static void* startThread(void* arg) এই পদ্ধতি রয়েছে: static void* startThread(void* arg)
এই পদ্ধতিতে একটি পয়েন্টার pthread_create(..) কল করার জন্য একটি যুক্তি হিসাবে ব্যবহার করা হবে। এবং startThread(..) প্রাপ্ত হওয়া উচিত কোনও Functor ক্লাসের Functor একটি উদাহরণের একটি void* বর্ণিত রেফারেন্স, যা কার্যকর হলে Functor* ফিরে যাওয়া হবে এবং তারপরে এটি run() পদ্ধতি বলা হবে।


নামটি "ফন্টক্টর" প্রচলিত ধারাবাহিকভাবে ব্যবহৃত হয়েছে যা তত্ত্বের ক্ষেত্রে সি ++ দৃশ্যের আগে উপস্থিত হয়েছিল। এই ফাংশক এর সি ++ ধারণা সঙ্গে কিছুই করার আছে। C ++ এ আমরা "ফন্টক্টর" কল করার পরিবর্তে নাম ফাংশন অবজেক্টটি ব্যবহার করা ভাল। এইভাবে অন্যান্য প্রোগ্রামিং ভাষা অনুরূপ গঠন কল।

সাধারণ ফাংশন পরিবর্তে ব্যবহার করা হয়:

বৈশিষ্ট্য:

  • ফাংশন বস্তুর রাষ্ট্র থাকতে পারে
  • ফাংশন অবজেক্ট ওওপিতে ফিট করে (এটি অন্য সকল বস্তুর মত আচরণ করে)।

কনস:

  • প্রোগ্রাম আরো জটিলতা এনেছে।

ফাংশন পয়েন্টার পরিবর্তে ব্যবহৃত:

বৈশিষ্ট্য:

  • ফাংশন বস্তু প্রায়ই ইনলাইন করা হতে পারে

কনস:

  • ফাংশন অবজেক্টটি রানটাইম সময় অন্যান্য ফাংশন অবজেক্ট টাইপের সাথে স্য্যাপড করা যাবে না (অন্তত এটি কিছু বেস ক্লাস প্রসারিত না করে, যা কিছু অতিরিক্ত ওভারহেড দেয়)

পরিবর্তে ভার্চুয়াল ফাংশন ব্যবহার করা হয়:

বৈশিষ্ট্য:

  • ফাংশন অবজেক্ট (অ ভার্চুয়াল) Vtable এবং রানটাইম প্রেরণ প্রয়োজন হয় না, এইভাবে এটি বেশিরভাগ ক্ষেত্রে আরো দক্ষ

কনস:

  • ফাংশন অবজেক্টটি রানটাইম সময় অন্যান্য ফাংশন অবজেক্ট টাইপের সাথে স্য্যাপড করা যাবে না (অন্তত এটি কিছু বেস ক্লাস প্রসারিত না করে, যা কিছু অতিরিক্ত ওভারহেড দেয়)

যোগ করার জন্য, আমি কমান্ড প্যাটার্নের বিদ্যমান লিগ্যাসি পদ্ধতিতে মাপসই করার জন্য ফাংশন অবজেক্টগুলি ব্যবহার করেছি; (শুধুমাত্র স্থান যেখানে OO রুপান্তরিত সত্য OCP আমি অনুভূত); এছাড়াও সম্পর্কিত ফাংশন অ্যাডাপ্টারের প্যাটার্ন এখানে যোগ করা।

আপনার পদ্ধতি স্বাক্ষর আছে ধরুন:

int CTask::ThreeParameterTask(int par1, int par2, int par3)

আমরা দেখব কিভাবে আমরা কমান্ড প্যাটার্নের জন্য এটি মাপসই করতে পারি - এর জন্য প্রথমে আপনাকে একটি ফাংশন অ্যাডাপ্টার লিখতে হবে যাতে এটি ফাংশন অবজেক্ট হিসাবে বলা যেতে পারে।

নোট - এটি কুৎসিত, এবং আপনি বুস্ট বাইন্ড হেল্পার ইত্যাদি ব্যবহার করতে পারেন, তবে আপনি যদি না চান বা না করতে চান তবে এটি একটি উপায়।

// a template class for converting a member function of the type int        function(int,int,int)
//to be called as a function object
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
class mem_fun3_t
{
  public:
explicit mem_fun3_t(_Ret (_Class::*_Pm)(_arg1,_arg2,_arg3))
    :m_Ptr(_Pm) //okay here we store the member function pointer for later use
    {}

//this operator call comes from the bind method
_Ret operator()(_Class *_P, _arg1 arg1, _arg2 arg2, _arg3 arg3) const
{
    return ((_P->*m_Ptr)(arg1,arg2,arg3));
}
private:
_Ret (_Class::*m_Ptr)(_arg1,_arg2,_arg3);// method pointer signature
};

এছাড়াও, কলিংয়ের জন্য উপরের ক্লাসের জন্য আমাদের একটি সহায়ক পদ্ধতি mem_fun3 প্রয়োজন।

template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
mem_fun3_t<_Ret,_Class,_arg1,_arg2,_arg3> mem_fun3 ( _Ret (_Class::*_Pm)          (_arg1,_arg2,_arg3) )
{
  return (mem_fun3_t<_Ret,_Class,_arg1,_arg2,_arg3>(_Pm));

}

এখন, পরামিতি বাঁধার জন্য, আমাদের একটি বাইন্ডার ফাংশন লিখতে হবে। সুতরাং, এখানে এটি যায়:

template<typename _Func,typename _Ptr,typename _arg1,typename _arg2,typename _arg3>
class binder3
{
public:
//This is the constructor that does the binding part
binder3(_Func fn,_Ptr ptr,_arg1 i,_arg2 j,_arg3 k)
    :m_ptr(ptr),m_fn(fn),m1(i),m2(j),m3(k){}

 //and this is the function object 
 void operator()() const
 {
        m_fn(m_ptr,m1,m2,m3);//that calls the operator
    }
private:
    _Ptr m_ptr;
    _Func m_fn;
    _arg1 m1; _arg2 m2; _arg3 m3;
};

এবং, একটি সহায়ক ফাংশন binder3 ক্লাস ব্যবহার করতে - bind3:

//a helper function to call binder3
template <typename _Func, typename _P1,typename _arg1,typename _arg2,typename _arg3>
binder3<_Func, _P1, _arg1, _arg2, _arg3> bind3(_Func func, _P1 p1,_arg1 i,_arg2 j,_arg3 k)
{
    return binder3<_Func, _P1, _arg1, _arg2, _arg3> (func, p1,i,j,k);
}

এখন, আমাদের কমান্ড ক্লাসের সাথে এটি ব্যবহার করতে হবে; নিম্নলিখিত typedef ব্যবহার করুন:

typedef binder3<mem_fun3_t<int,T,int,int,int> ,T* ,int,int,int> F3;
//and change the signature of the ctor
//just to illustrate the usage with a method signature taking more than one parameter
explicit Command(T* pObj,F3* p_method,long timeout,const char* key,
long priority = PRIO_NORMAL ):
m_objptr(pObj),m_timeout(timeout),m_key(key),m_value(priority),method1(0),method0(0),
method(0)
{
    method3 = p_method;
}

এখানে আপনি কিভাবে এটি কল করেন:

F3 f3 = PluginThreadPool::bind3( PluginThreadPool::mem_fun3( 
      &CTask::ThreeParameterTask), task1,2122,23 );

দ্রষ্টব্য: f3 (); পদ্ধতি টাস্ক 1-> তিনপ্যারিমিটার টাস্ক (21,22,23) কল করবে;

নিম্নলিখিত link এ এই প্যাটার্ন পূর্ণ প্রেক্ষাপটে


লাইক পুনরাবৃত্তি করা হয়েছে, ফ্যাক্টর ক্লাস হয় যে ফাংশন হিসাবে গণ্য করা যেতে পারে (ওভারলোড অপারেটর ())।

তারা এমন পরিস্থিতিগুলির জন্য সবচেয়ে উপযোগী যা আপনাকে কোনও ফাংশনে পুনরাবৃত্তি বা বিলম্বিত কলগুলির সাথে কিছু তথ্য সংযুক্ত করতে হবে।

উদাহরণস্বরূপ, মৌলিক লো-ওভারহেড সিঙ্ক্রোনাস কোরাউটিন সিস্টেম, একটি টাস্ক ডিসপাচার, বা বিঘ্নিত ফাইল পার্সিং বাস্তবায়নের জন্য ফন্টকটারগুলির একটি লিঙ্ক-তালিকা ব্যবহার করা যেতে পারে। উদাহরণ:

/* prints "this is a very simple and poorly used task queue" */
class Functor
{
public:
    std::string output;
    Functor(const std::string& out): output(out){}
    operator()() const
    {
        std::cout << output << " ";
    }
};

int main(int argc, char **argv)
{
    std::list<Functor> taskQueue;
    taskQueue.push_back(Functor("this"));
    taskQueue.push_back(Functor("is a"));
    taskQueue.push_back(Functor("very simple"));
    taskQueue.push_back(Functor("and poorly used"));
    taskQueue.push_back(Functor("task queue"));
    for(std::list<Functor>::iterator it = taskQueue.begin();
        it != taskQueue.end(); ++it)
    {
        *it();
    }
    return 0;
}

/* prints the value stored in "i", then asks you if you want to increment it */
int i;
bool should_increment;
int doSomeWork()
{
    std::cout << "i = " << i << std::endl;
    std::cout << "increment? (enter the number 1 to increment, 0 otherwise" << std::endl;
    std::cin >> should_increment;
    return 2;
}
void doSensitiveWork()
{
     ++i;
     should_increment = false;
}
class BaseCoroutine
{
public:
    BaseCoroutine(int stat): status(stat), waiting(false){}
    void operator()(){ status = perform(); }
    int getStatus() const { return status; }
protected:
    int status;
    bool waiting;
    virtual int perform() = 0;
    bool await_status(BaseCoroutine& other, int stat, int change)
    {
        if(!waiting)
        {
            waiting = true;
        }
        if(other.getStatus() == stat)
        {
            status = change;
            waiting = false;
        }
        return !waiting;
    }
}

class MyCoroutine1: public BaseCoroutine
{
public:
    MyCoroutine1(BaseCoroutine& other): BaseCoroutine(1), partner(other){}
protected:
    BaseCoroutine& partner;
    virtual int perform()
    {
        if(getStatus() == 1)
            return doSomeWork();
        if(getStatus() == 2)
        {
            if(await_status(partner, 1))
                return 1;
            else if(i == 100)
                return 0;
            else
                return 2;
        }
    }
};

class MyCoroutine2: public BaseCoroutine
{
public:
    MyCoroutine2(bool& work_signal): BaseCoroutine(1), ready(work_signal) {}
protected:
    bool& work_signal;
    virtual int perform()
    {
        if(i == 100)
            return 0;
        if(work_signal)
        {
            doSensitiveWork();
            return 2;
        }
        return 1;
    }
};

int main()
{
     std::list<BaseCoroutine* > coroutineList;
     MyCoroutine2 *incrementer = new MyCoroutine2(should_increment);
     MyCoroutine1 *printer = new MyCoroutine1(incrementer);

     while(coroutineList.size())
     {
         for(std::list<BaseCoroutine *>::iterator it = coroutineList.begin();
             it != coroutineList.end(); ++it)
         {
             *it();
             if(*it.getStatus() == 0)
             {
                 coroutineList.erase(it);
             }
         }
     }
     delete printer;
     delete incrementer;
     return 0;
}

অবশ্যই, এই উদাহরণ নিজেদের মধ্যে দরকারী নয়। তারা শুধুমাত্র কীভাবে ফ্যান্টাকটরগুলি উপকারী হতে পারে তা দেখায়, ফ্যাক্টরগুলি খুব মৌলিক এবং নমনীয় এবং এটি তাদের থেকে কম কার্যকর করে তোলে, উদাহরণস্বরূপ, কোন সহায়তা প্রদান করে।





function-call-operator