2009-09-07 37 views

Trả lời

5

Bạn không thể làm điều đó, thực sự, nhưng bạn có thể giả mạo nó. Đây là a way you can fake it in C, bạn cũng có thể sử dụng trong C++.

+1

+1 chính xác những gì tôi định nói, mặc dù không có sự khác biệt nào giữa "giả mạo" và "triển khai". Tôi nghi ngờ rằng trong C++ bạn có thể muốn trạng thái coroutine trong các biến thành viên của một functor, và gọi nó, với các trường hợp khác nhau khi thích hợp, thay vì sử dụng globals và gọi một hàm có tên là anakin. Bạn có thể làm một điều tương tự trong C với một tham số bổ sung, nhưng ít có khả năng muốn. –

1

Gọi một coroutine nhiều lần và nhận các câu trả lời khác nhau có nghĩa là bạn giữ một số trạng thái. Cách giữ trạng thái là đối tượng. Cách làm cho chúng trông giống như gọi hàm là toán tử quá tải. Xem http://en.wikipedia.org/wiki/Function_object.

11

Trong C++, chúng tôi có 'trình lặp'. Một yêu cầu rõ ràng cho một interator, rõ ràng increments nó và dereferences nó.

Nếu bạn muốn chúng được sử dụng với các chức năng thư viện chuẩn, chúng chủ yếu được lấy từ std::forward_iterator và triển khai một số chức năng của nó.

Một cách khác để bắt chước kindof một máy phát điện trên một bộ sưu tập được cho phép một hàm như là đối số để một hàm thành viên đó nguồn cấp dữ liệu (sản lượng) tất cả của nó giá trị là chức năng mà:

struct MyCollection { 
    int values[30]; 

    template< typename F > 
    void generate(F& yield_function) const { 
     int* end = values+30; // make this better in your own code :) 
     for(auto i: values) yield_function(*i); 
    } 
}; 

// usage: 
c.generate([](int i){ std::cout << i << std::endl; }); 

// or pre-C++11: 
struct MyFunction { 
    void operator() (int i)const { printf("%d\n", i); } 
}; 
MyCollection c; 
c.generate(MyFunction()); 
5

Để xây dựng trên các iterator thực hiện: đây là một ví dụ. Nó có thể được sử dụng như một biến vòng lặp, hoặc trong các thuật toán std.

#include <iterator> 

template< typename T, typename TDiff = T > 
struct TGenerator : public std::iterator<std::forward_iterator_tag,T,TDiff> { 
    T from,to; 
    T value; 
    TDiff step; 
    bool issentinel; 

    TGenerator(T from, T to, TDiff step, bool sentinel = false) 
    : from(from),to(to),step(step),issentinel(sentinel), value(from) 
    {} 

    void operator++(){ value += step; } 

    const T& operator*()const { return value; } 

    bool operator!=(const TGenerator& other) const { 
    return value<to; 
    } 

    TGenerator sentinel()const { return TGenerator(0,0,0,true); } 

}; 


#include <algorithm> 
#include <iostream> 

int main() 
{ 
    TGenerator<int> i(0,10,3); 
    std::copy(i, i.sentinel(), std::ostream_iterator<int>(std::cout, " ")); 

    return 0; 
} 
+0

Tham số thứ ba của hàm tạo 'TGenerator' phải là' TDiff step' thay vì 'T step'. – vvnurmi

+0

Cảm ơn! Sửa lỗi đó. – xtofl

1

bạn có thể sử dụng boost.context (xin lỗi, không phải trên phân phối tăng nào, bạn sẽ có để có được nó từ boost vault).

Một mã ví dụ điển hình sẽ là như thế này:

#include <iostream> 
#include <boost/context.hpp> 

using namespace std; 

struct Parameters { 
    int par1; 
    float par2; 
}; 

boost::context c1; 
boost::context c2; 

void F(void* parameters) { 
    Parameters& pars = *(Parameters*)parameters; 
    cout << pars.par1 << endl; 
    c2.jump_to(c1); 
    cout << pars.par2 << endl; 
}; 

int main() { 
    c1 = boost::context::current(); 
    Parameters p; 
    p.par1 = 8; 
    c2 = boost::context::create_context(F , c1 , p); 
    c1.jump_to(c2); 
    p.par2 = 1.3; 
    c1.jump_to(c2); 
} 
8

này ... Gentlemen ... được tinh khiết ma thuật đen:

http://www.codeproject.com/Articles/29524/Generators-in-C

Tôi đã thử nó, và nó thậm chí hoạt động đệ quy. Tôi đã sử dụng nó thường xuyên kể từ đó. Máy phát điện, gần như là công dân hạng nhất trong C++. Thậm chí không có bất kỳ chi phí hiệu suất nào.

Với sự tôn trọng sâu sắc nhất của tôi đối với tác giả

+1

Nó không phải là ma thuật đen _that_ ... tuy nhiên, nó là rất un-C++ 11-ish. – einpoklum

Các vấn đề liên quan