2009-09-07 10 views

Odpowiedz

5

Nie możesz tego zrobić, naprawdę, ale możesz to udawać. Oto a way you can fake it in C, którego można używać również w C++.

+1

+1 dokładnie to, co zamierzałem powiedzieć, chociaż nie ma żadnej różnicy między "fałszowaniem" i "realizowaniem". Podejrzewam, że w C++ możesz chcieć stanu coroutine w elementarnych zmiennych funktora i wywoływać to, używając różnych instancji, zamiast używać globali i wywoływać nazwaną funkcję jako anakin. Możesz zrobić coś podobnego w C z dodatkowym parametrem, ale jest mniej prawdopodobne, że chcesz. –

11

W C++ mamy "iteratory". Jeden z nich wyraźnie prosi o interwenienta, wyraźnie go zwiększa i usuwa.

Jeśli chcesz, aby były używane ze standardowymi funkcjami biblioteki, powinny one być w większości wyprowadzane z std::forward_iterator i implementować pewną liczbę jego funkcji.

Innym sposobem, aby naśladować kindof generator na zbiorze jest umożliwienie funkcję jako argument do funkcji składowej, która karmi (Yield) wszystkich jego wartości do tej funkcji:

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

wypracowanie na iteracyjnej realizacja: to jest przykład. Może być używany jako zmienna pętli lub w algorytmach standardowych.

#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

Trzeci parametr trzeciego konstruktora TGeneratora powinien być 'Krok TDiff' zamiast' T step'. – vvnurmi

+0

Dzięki! Naprawiono to. – xtofl

1

można użyć boost.context (przepraszam, nie w sprawie podziału doładowania jeszcze, będziesz musiał dostać od boost vault).

Typowym przykładem kod byłoby tak:

#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

... Panowie ... To jest czysta czarna magia:

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

Próbowałem go, i nawet działa rekurencyjnie. Od tego czasu używam go regularnie. Generatory, prawie jako pierwszorzędni obywatele w C++. Nie ma nawet żadnego obciążenia wydajnościowego.

Z mojego najgłębszego szacunku do autora

+1

To nie jest ta czarna magia ... jednak jest bardzo nie-C++ 11-ish. – einpoklum