我有点理解这一点,至少是生成器的功能(我在Python中使用过它们)。我理解switch语句及其内容是如何形成的。但是,我收到了这些错误。
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;
}
答案 0 :(得分: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
答案 1 :(得分: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
Foo *
通过descent
构造函数传入,并使用Foo *
引用index_
和{{1} } - 或将必要的成员移动到bars_
。
说实话,我真的不明白这里的descent
是什么......它所做的一切似乎都属于Foo
。