2009-10-22 4 views
1

일종의 제네레이터 (적어도 파이썬에서 사용한 적이 있습니다)의 기능을 이해합니다. switch 문과 내용이 어떻게 형성되는지 이해합니다. 그러나 이러한 오류가 발생합니다.C++의 생성자 - 비 정적 데이터 멤버의 잘못된 사용

test.cpp: In constructor 'Foo::descent::descent(int)': 
test.cpp:46: error: invalid use of nonstatic data member 'Foo::index_' 
test.cpp: In member function 'bool Foo::descent::operator()(std::string&)': 
test.cpp:50: error: invalid use of nonstatic data member 'Foo::bars_' 
test.cpp:50: error: invalid use of nonstatic data member 'Foo::index_' 
test.cpp:51: error: invalid use of nonstatic data member 'Foo::index_' 
test.cpp:51: error: invalid use of nonstatic data member 'Foo::bars_' 
test.cpp:52: error: invalid use of nonstatic data member 'Foo::index_' 

다음은 코드입니다. 이 문제를 해결할 더 좋은 방법이 있다면 꼭 공유하십시오. 당신의 오류가 발생하는 위치를

#include <math.h> 
#include <string> 
#include <vector> 
#include <iostream> 

#ifndef __generator_h__ 
#define __generator_h__ 

// generator/continuation for C++ 
// author: Andrew Fedoniouk @ terrainformatica.com 
// idea borrowed from: "coroutines in C" Simon Tatham, 
//      http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html 

struct _generator 
{ 
    int _line; 
    _generator():_line(0) {} 
}; 

#define $generator(NAME) struct NAME : public _generator 

#define $emit(T) bool operator()(T& _rv) { \ 
        switch(_line) { case 0:; 

#define $stop } _line = 0; return false; } 

#define $yield(V)  \ 
     do {\ 
      _line=__LINE__;\ 
      _rv = (V); return true; case __LINE__:;\ 
     } while (0) 
#endif 

class Foo { 
    int index_; 
    std::vector<std::string> bars_; 
    public: 
    Foo() { 
     index_ = 0; 
     bars_.push_back("Foobar"); 
     bars_.push_back("Barfoo"); 
    } 
    $generator(descent){ 
     int j; 
     descent(int j) { 
      index_+=j; 
     } 
     $emit(std::string) 
      while(true) { 
       $yield(bars_[index_++]); 
       if(index_ >= bars_.size()) 
        index_ = 0; 
      } 
     $stop; 
    }; 
    //descent bar; 
    void InitGenerator() { index_ = 0; } 
}; 

using namespace std; 

int main() 
{ 
    //Foo::descent gen(1); 
    //for(int n; gen(n);) // "get next" generator invocation 
    // cout << n << endl; 
    return 0; 
} 
+1

그래서 당신이 할하려는 거죠? – stefanB

+5

와우, #define에서 '$'를 사용할 수 있는지 몰랐다. –

+1

당신은'#define BEGIN {'을 사용하고 이것을 약간 좋아한다. C++로도 Pascal을 프로그래밍 할 수있다. 그러나 그렇다고해서 언어를 남용하는 것이 좋은 생각은 아닙니다. 그것은 내가 해독하기 시작하고 싶지 않은 끔찍한 코드입니다. (C와 C++의 거의 20 년 후에,'$ '를 포함하는 매크로를 가질 수 있는지조차 알지 못했습니다. 그렇습니다. 자주 사용됩니다.) C++에서하는 방법을 배우십시오.좋은 시작은 목표를 진술하고 C++에서 그것을 성취하는 방법을 묻는 새로운 질문 일 수 있습니다. – sbi

답변

4

내가 여기 당신이 여기가는하는지 완전히 잘 모르겠지만,는 다음과 같습니다

이의이 정말 어떻게 보이는지 확인하기 위해 매크로를 확장하자

class Foo { 
    int index_; 
    std::vector<std::string> bars_; 
    public: 
    Foo() { 
     index_ = 0; 
     bars_.push_back("Foobar"); 
     bars_.push_back("Barfoo"); 
    } 
    struct descent: public _generator { 
     int j; 
     descent(int j) { 
      index_+=j; 
     } 
     bool operator()(std::string& _rv) { 
     switch(_line) { case 0:; 
      while(true) { 
       do { 
        _line=__LINE__; 
        _rv = (bars_[index_++]); return true; case __LINE__:; 
       } while (0); 
       if(index_ >= bars_.size()) 
        index_ = 0; 
      } 
     } _line = 0; return false; } 
    }; 
    //descent bar; 
    void InitGenerator() { index_ = 0; } 
}; 

보시다시피, 우리는 내부 구조를 선언합니다 Foo::descent. 그러나 다른 언어와 달리 C++의 내부 클래스는 자동으로 외부 클래스의 인스턴스에 대한 포인터를 갖지 않습니다. 또는 오른쪽 descent에 필요한 멤버를 이동 - 당신은 descentdescent 생성자를 통해 전달되는 Foo *에 추가하고, index_bars_를 참조하는 것을 Foo *을 사용하거나해야합니다.

솔직히 말해서 나는 여기에 전혀 Foo이 무엇인지 이해하지 못한다 ... 모든 것이 바로 descent에 속하는 것으로 보인다.

+0

자, descent 객체를 다시 초기화 할 수 있어야하지만 index_ 상태를 유지해야합니다. Foo의 인스턴스가 여러 개 있기 때문에 정적 일 수 없습니다. – Scott

+0

그건 효과가있어, Foo *. – Scott

+1

@Scott 귀하의 의견은 귀하의 코드와 모순되는 것 같습니다 descent (int j)는 인덱스만을 수정하는 것 같습니다.하지만 인덱스를 유지하고 나머지를 재설정하고 싶다고 말한 것입니다. 여전히 귀하의 코드는 그것이하기로되어있는 간단한 일. C++로 전환하거나 Python으로 이동하십시오. – stefanB

7

본인이 본인 이니?

generator을 반환 하시겠습니까?하지만 원하는대로 수정하십시오.

아이디어는 생성자 개체가 자신의 상태를 유지하고 메서드를 호출하면 다시 다음 값을 제공한다는 아이디어입니다. 반환 할 상태와 다음 값으로 정의한 것은 전적으로 사용자에게 달려 있습니다.

operator()operator()(bool b에서와 같이 매개 변수) 또는 operator()(char * c)뿐만 아니라 어떤 가치 당신이 원하는 수익을 받아 들일 수 ...

#include <iostream> 
#include <vector> 
#include <string> 
using namespace std; 

struct generator 
{ 
    generator() : currentCh(0), currentW(0), str(0), words() 
    { // do whatever initialization you need 
     words.push_back("Foobar"); 
     words.push_back("Barfoo"); 
     str = &words[currentW]; 
    } 

    char operator()() 
    { // use whatever logic you need 
     if (currentCh >= str->size()) 
     { 
      if (++currentW >= words.size()) currentW = 0; 
      str = &words[currentW]; 
      currentCh = 0; 
     } 
     return str->at(currentCh++); 
    } 

    unsigned int currentCh; 
    unsigned int currentW; 
    string * str; 
    vector<string> words; 
}; 

당신은 예를 들어 추가, 어쨌든 당신이 좋아하는 내부 상태를 업데이트 할 수 있습니다

코드에서 다음
char operator()(unsigned int index) 
{ 
    currentCh = index; 
    return this->operator()(); 
} 

어딘가에 당신은 할 수 있습니다 :

generator g; 
g(); // get first character 
g(2); // resets the index in this case ... 
g(); // get next character (the logic is a bit off but it depends what you need) 

사용법 :

int main() 
{ 
    generator g; 
    for (unsigned int i = 30; --i;) cout << g() << endl; 
} 

출력 :

F 
o 
o 
b 
a 
r 
B 
a 
r 
f 
o 
o 
F 
o 
o 
b 
a 
r 
B 
a 
r 
f 
o 
o 
F 
o 
o 
b 
a 
관련 문제