referencing "this" in a static method

A

Aryeh M. Friedman

Why is the value of "Instance" whacked in the following code. Note this
only happens in Graph::*Wrapper.

Also please note that if I hardcode WalkFunc and PrintFunct to be
BredthFirst and BredthFirstPrint and make both approriate func ptrs it works
fine.
void print(void *data);

#define R 'r'-'r'
#define S 's'-'r'
#define T 't'-'r'
#define U 'u'-'r'
#define V 'v'-'r'
#define W 'w'-'r'
#define X 'x'-'r'
#define Y 'y'-'r'

int main()
{
int i;
Graph *graph;
char *s="rstuvwxy";

graph=graph->init();

for(i=0;i<8;i++)
graph->addNode(&s);

graph->addEdge(&s[R],&s);
graph->addEdge(&s[R],&s[V]);
graph->addEdge(&s,&s[W]);
graph->addEdge(&s[W],&s);
graph->addEdge(&s[W],&s[T]);
graph->addEdge(&s[T],&s[X]);
graph->addEdge(&s[T],&s);
graph->addEdge(&s,&s[Y]);
graph->addEdge(&s[X],&s[Y]);

graph->walk();
graph->print(print,&s[R],&s[Y]);
}

void print(void *data)
{
cout<<*RI_CAST<char *>(data)<<endl;
}
class Graph {
public:
Graph *init(unsigned long walkfunc=0,unsigned long printfunc=0);

void addNode(void *data);
void addEdge(void *d1, void *d2);

GNode *findNode(void *data);
void walk();
void print(void (*func)(void *data),void *d1,void *d2);

static void BredthFirstWrapper();
static void
BredthFirstPrintWrapper(void (*func)(void *data),GNode
*node,GNode *node2);

void Dump();

//protected:
Graph(unsigned long walkfunc=0,unsigned long printfunc=0);

private:
void BredthFirst();
void BredthFirstPrint(void (*func)(void *data),GNode *node,GNode
*node2);
void reset();

static Graph *Instance;

LinkedList *Nodes;
unsigned long WalkFunc;
unsigned long PrintFunc;
};


Graph *Graph::Instance=0;

Graph *Graph::init(unsigned long walkfunc,unsigned long printfunc)
{
return new Graph(walkfunc,printfunc);
}

void Graph::addNode(void *data)
{
GNode *node;

node=node->init(data);
Nodes->addNode(node);
}

void Graph::addEdge(void *d1,void *d2)
{
GNode *node;
GNode *node2;

node=findNode(d1);
node2=findNode(d2);

node->addEdge(node2);
node2->addEdge(node);
}

GNode *Graph::findNode(void *data)
{
GNode *node;

Nodes->reset(); // paranoia
while((node=RI_CAST<GNode *>(Nodes->getNext()))!=0)
if(node->getData()==data) {
Nodes->reset();

return node;
}

Nodes->reset();

return 0;
}

void Graph::walk()
{
Instance=this;
(RI_CAST<void (*)(Graph *)>(WalkFunc))(this);
}

void Graph::print(void (*func)(void *data),void *d1,void *d2)
{
GNode *node;
GNode *node2;

node=findNode(d1);
node2=findNode(d2);

if(node==0||node2==0) {
cout<<"Can't find one of the path ends for this graph print"<<endl;
exit(1);
}

Instance=this;
(RI_CAST<void (*)(Graph *,void (*)(void *),GNode *, GNode *)>(PrintFunc))
(this,func,node,node2);
}

void Graph::BredthFirstWrapper()
{
if(Instance==0)
return;

Instance->BredthFirst();
}

void Graph::BredthFirstPrintWrapper(void (*func)(void *data),GNode
*node,GNode *node2)
{
if(Instance==0)
return;

cout<<node<<" "<<node2<<endl;
Instance->BredthFirstPrint(func,node,node2);
}

void Graph::Dump()
{
GNode *node;

cout<<"Nodes: "<<endl;

while((node=RI_CAST<GNode *>(Nodes->getNext()))!=0)
node->Dump();

Nodes->reset();
}

Graph::Graph(unsigned long walkfunc,unsigned long printfunc)
{
Nodes=Nodes->init();

if(walkfunc==0)
walkfunc=RI_CAST<unsigned long>(&Graph::BredthFirstWrapper);

WalkFunc=(walkfunc);

if(printfunc==0)
printfunc=RI_CAST<unsigned long>(&Graph::BredthFirstPrintWrapper);

PrintFunc=printfunc;
}

void Graph::BredthFirst()
{
GNode *node;
GNode *tmp;
Queue *queue;
LinkedList *edges;

reset();

node=RI_CAST<GNode *>(Nodes->getNext());
if(node==0)
return;

node->setColor(GNodeColorGrey);

queue=queue->init();
queue->insert(node);

node->setDepth(0);
node->setPrev(0);

do {
node=RI_CAST<GNode *>(queue->peek());
cout<<"processing node "<<node<<endl;
edges=node->getEdges();

while((tmp=RI_CAST<GNode *>(edges->getNext()))!=0)
if(tmp->getColor()==GNodeColorWhite) {
tmp->setColor(GNodeColorGrey);
tmp->setDepth(node->getDepth()+1);
tmp->setPrev(node);

queue->insert(tmp);
}

edges->reset();

node=RI_CAST<GNode *>(queue->get());

if(node==0)
break;

node->setColor(GNodeColorBlack);
} while(queue->getSize()>0);
}

void Graph::BredthFirstPrint(void (*func)(void *data),GNode *node, GNode
*node2)
{
if(node==node2) {
func(node->getData());
return;
}

if(node2->getPrev()==0) {
cout<<"No path from "<<node<<" to "<<node2<<endl;
exit(1);
}

BredthFirstPrint(func,node,node2->getPrev());
func(node2->getData());
}

void Graph::reset()
{
GNode *node;

while((node=RI_CAST<GNode *>(Nodes->getNext()))!=0)
node->reset();

Nodes->reset();
}
 
E

Efrat Regev

You might want to shorten and simplify your code, to pinpoint what fails.
This way you will either
1. find the bug
2. be able to post a message which more people might go over

Aryeh M. Friedman said:
Why is the value of "Instance" whacked in the following code. Note this
only happens in Graph::*Wrapper.

Also please note that if I hardcode WalkFunc and PrintFunct to be
BredthFirst and BredthFirstPrint and make both approriate func ptrs it works
fine.
void print(void *data);

#define R 'r'-'r'
#define S 's'-'r'
#define T 't'-'r'
#define U 'u'-'r'
#define V 'v'-'r'
#define W 'w'-'r'
#define X 'x'-'r'
#define Y 'y'-'r'

int main()
{
int i;
Graph *graph;
char *s="rstuvwxy";

graph=graph->init();

for(i=0;i<8;i++)
graph->addNode(&s);

graph->addEdge(&s[R],&s);
graph->addEdge(&s[R],&s[V]);
graph->addEdge(&s,&s[W]);
graph->addEdge(&s[W],&s);
graph->addEdge(&s[W],&s[T]);
graph->addEdge(&s[T],&s[X]);
graph->addEdge(&s[T],&s);
graph->addEdge(&s,&s[Y]);
graph->addEdge(&s[X],&s[Y]);

graph->walk();
graph->print(print,&s[R],&s[Y]);
}

void print(void *data)
{
cout<<*RI_CAST<char *>(data)<<endl;
}
class Graph {
public:
Graph *init(unsigned long walkfunc=0,unsigned long printfunc=0);

void addNode(void *data);
void addEdge(void *d1, void *d2);

GNode *findNode(void *data);
void walk();
void print(void (*func)(void *data),void *d1,void *d2);

static void BredthFirstWrapper();
static void
BredthFirstPrintWrapper(void (*func)(void *data),GNode
*node,GNode *node2);

void Dump();

//protected:
Graph(unsigned long walkfunc=0,unsigned long printfunc=0);

private:
void BredthFirst();
void BredthFirstPrint(void (*func)(void *data),GNode *node,GNode
*node2);
void reset();

static Graph *Instance;

LinkedList *Nodes;
unsigned long WalkFunc;
unsigned long PrintFunc;
};


Graph *Graph::Instance=0;

Graph *Graph::init(unsigned long walkfunc,unsigned long printfunc)
{
return new Graph(walkfunc,printfunc);
}

void Graph::addNode(void *data)
{
GNode *node;

node=node->init(data);
Nodes->addNode(node);
}

void Graph::addEdge(void *d1,void *d2)
{
GNode *node;
GNode *node2;

node=findNode(d1);
node2=findNode(d2);

node->addEdge(node2);
node2->addEdge(node);
}

GNode *Graph::findNode(void *data)
{
GNode *node;

Nodes->reset(); // paranoia
while((node=RI_CAST<GNode *>(Nodes->getNext()))!=0)
if(node->getData()==data) {
Nodes->reset();

return node;
}

Nodes->reset();

return 0;
}

void Graph::walk()
{
Instance=this;
(RI_CAST<void (*)(Graph *)>(WalkFunc))(this);
}

void Graph::print(void (*func)(void *data),void *d1,void *d2)
{
GNode *node;
GNode *node2;

node=findNode(d1);
node2=findNode(d2);

if(node==0||node2==0) {
cout<<"Can't find one of the path ends for this graph print"<<endl;
exit(1);
}

Instance=this;
(RI_CAST<void (*)(Graph *,void (*)(void *),GNode *, GNode *)>(PrintFunc))
(this,func,node,node2);
}

void Graph::BredthFirstWrapper()
{
if(Instance==0)
return;

Instance->BredthFirst();
}

void Graph::BredthFirstPrintWrapper(void (*func)(void *data),GNode
*node,GNode *node2)
{
if(Instance==0)
return;

cout<<node<<" "<<node2<<endl;
Instance->BredthFirstPrint(func,node,node2);
}

void Graph::Dump()
{
GNode *node;

cout<<"Nodes: "<<endl;

while((node=RI_CAST<GNode *>(Nodes->getNext()))!=0)
node->Dump();

Nodes->reset();
}

Graph::Graph(unsigned long walkfunc,unsigned long printfunc)
{
Nodes=Nodes->init();

if(walkfunc==0)
walkfunc=RI_CAST<unsigned long>(&Graph::BredthFirstWrapper);

WalkFunc=(walkfunc);

if(printfunc==0)
printfunc=RI_CAST<unsigned long>(&Graph::BredthFirstPrintWrapper);

PrintFunc=printfunc;
}

void Graph::BredthFirst()
{
GNode *node;
GNode *tmp;
Queue *queue;
LinkedList *edges;

reset();

node=RI_CAST<GNode *>(Nodes->getNext());
if(node==0)
return;

node->setColor(GNodeColorGrey);

queue=queue->init();
queue->insert(node);

node->setDepth(0);
node->setPrev(0);

do {
node=RI_CAST<GNode *>(queue->peek());
cout<<"processing node "<<node<<endl;
edges=node->getEdges();

while((tmp=RI_CAST<GNode *>(edges->getNext()))!=0)
if(tmp->getColor()==GNodeColorWhite) {
tmp->setColor(GNodeColorGrey);
tmp->setDepth(node->getDepth()+1);
tmp->setPrev(node);

queue->insert(tmp);
}

edges->reset();

node=RI_CAST<GNode *>(queue->get());

if(node==0)
break;

node->setColor(GNodeColorBlack);
} while(queue->getSize()>0);
}

void Graph::BredthFirstPrint(void (*func)(void *data),GNode *node, GNode
*node2)
{
if(node==node2) {
func(node->getData());
return;
}

if(node2->getPrev()==0) {
cout<<"No path from "<<node<<" to "<<node2<<endl;
exit(1);
}

BredthFirstPrint(func,node,node2->getPrev());
func(node2->getData());
}

void Graph::reset()
{
GNode *node;

while((node=RI_CAST<GNode *>(Nodes->getNext()))!=0)
node->reset();

Nodes->reset();
}
 
D

David White

Aryeh M. Friedman said:
Why is the value of "Instance" whacked in the following code. Note this
only happens in Graph::*Wrapper.

Also please note that if I hardcode WalkFunc and PrintFunct to be
BredthFirst and BredthFirstPrint and make both approriate func ptrs it works
fine.

You'd have to ask the programmer why it was done that way. It could be that
one or both static functions were intended to called from somewhere external
that didn't have access to the necessary instance, so the static Instance
was used. Or maybe there's only ever supposed to be one instance. There's a
lot of code and I don't have time to analyse it properly..

It all looks pretty horrible to me. I would want to get rid of 'Instance'
altogether if possible.

DW
 
A

Aryeh M. Friedman

David White said:
You'd have to ask the programmer why it was done that way. It could be
that

Ok I will ask myself why I did it this way ;-).... btw I found the issue
later which was
a junk arguement.
one or both static functions were intended to called from somewhere
external
that didn't have access to the necessary instance, so the static Instance
was used. Or maybe there's only ever supposed to be one instance. There's
a
lot of code and I don't have time to analyse it properly..

It all looks pretty horrible to me. I would want to get rid of 'Instance'
altogether if possible.

The reason is if your going to pass a non-default method to the factory
(Graph::init) the compiler barfs unless it is static. And "this" is
avaible from inside a static method. Thus Instance=this then call the
static wrapper and do Instance->real

--Aryeh
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,816
Latest member
SapanaCarpetStudio

Latest Threads

Top