doubt with Templates<> in A* implementation[SOLVED]

Get answers to all your basic programming questions. No Ogre questions, please!
Blender+C++
Gremlin
Posts: 171
Joined: Tue Jan 03, 2012 1:38 am
Location: Brazil
x 3

doubt with Templates<> in A* implementation[SOLVED]

Post by Blender+C++ »

hello everyone,
i've been studying for over 2 weeks a simple example of A* pathfinding, not an ideal example for a complex terrain map(coz it uses a grid array for the coordinates) but it helps me somewhat to understand how to implement A* and integrate it with ogre 3d, i found a sample in this address : http://www.danielsoltyka.com/portfolio/ ... nstration/, and downloaded the VS file...so as i said for about 2 weeks ive been trying to understand it but im in doubt in some parts of it, parts which uses operator overloading methods and also templates, im still a newbie in c++ besides the fact that i already learned a lot from tutorials, hundreds of them btw.... sooo lets go straight to the point ...
we have this header file called : stlastar.h which holds the following code:

Code: Select all

/*
A* Algorithm Implementation using STL is
Copyright (C)2001-2005 Justin Heyes-Jones

Permission is given by the author to freely redistribute and 
include this code in any program as long as this credit is 
given where due.
 
  COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, 
  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, 
  INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE 
  IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
  OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND 
  PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED 
  CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL 
  DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY 
  NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF 
  WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE 
  OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
  THIS DISCLAIMER.
 
  Use at your own risk!

*/
#pragma once

// used for text debugging
#include <iostream>
#include <stdio.h>
//#include <conio.h>
#include <assert.h>

// stl includes
#include <algorithm>
#include <set>
#include <vector>

//using namespace std;

// fast fixed size memory allocator, used for fast node memory management
#include "fsa.h"

// Fixed size memory allocator can be disabled to compare performance
// Uses std new and delete instead if you turn it off
#define USE_FSA_MEMORY 1

// disable warning that debugging information has lines that are truncated
// occurs in stl headers
#pragma warning( disable : 4786 )

// The AStar search class. UserState is the users state space type
template <class UserState> class AStarSearch
{

public: // data

	enum
	{
		SEARCH_STATE_NOT_INITIALISED,
		SEARCH_STATE_SEARCHING,
		SEARCH_STATE_SUCCEEDED,
		SEARCH_STATE_FAILED,
		SEARCH_STATE_OUT_OF_MEMORY,
		SEARCH_STATE_INVALID
	};


	// A node represents a possible state in the search
	// The user provided state type is included inside this type

	public:

	class Node
	{
		public:

			Node *parent; // used during the search to record the parent of successor nodes
			Node *child; // used after the search for the application to view the search in reverse
			
			float g; // cost of this node + it's predecessors
			float h; // heuristic estimate of distance to goal
			float f; // sum of cumulative cost of predecessors and self and heuristic

			Node() :
				parent( 0 ),
				child( 0 ),
				g( 0.0f ),
				h( 0.0f ),
				f( 0.0f )
			{			
			}

			UserState m_UserState;
	};


	// For sorting the heap the STL needs compare function that lets us compare
	// the f value of two nodes

	class HeapCompare_f 
	{
		public:

			bool operator() ( const Node *x, const Node *y ) const
			{
				return x->f > y->f;
			}
	};


public: // methods


	// constructor just initialises private data
	AStarSearch( int MaxNodes = 1000 ) :
		m_AllocateNodeCount(0),
#if USE_FSA_MEMORY
		m_FixedSizeAllocator( MaxNodes ),
#endif
		m_State( SEARCH_STATE_NOT_INITIALISED ),
		m_CurrentSolutionNode( NULL ),
		m_CancelRequest( false )
	{
	}

	// call at any time to cancel the search and free up all the memory
	void CancelSearch()
	{
		m_CancelRequest = true;
	}

	// Set Start and goal states
	void SetStartAndGoalStates( UserState &Start, UserState &Goal )
	{
		m_CancelRequest = false;

		m_Start = AllocateNode();
		m_Goal = AllocateNode();

		assert((m_Start != NULL && m_Goal != NULL));
		
		m_Start->m_UserState = Start;
		m_Goal->m_UserState = Goal;

		m_State = SEARCH_STATE_SEARCHING;
		
		// Initialise the AStar specific parts of the Start Node
		// The user only needs fill out the state information

		m_Start->g = 0; 
		m_Start->h = m_Start->m_UserState.GoalDistanceEstimate( m_Goal->m_UserState );
		m_Start->f = m_Start->g + m_Start->h;
		m_Start->parent = 0;

		// Push the start node on the Open list

		m_OpenList.push_back( m_Start ); // heap now unsorted

		// Sort back element into heap
		push_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() );

		// Initialise counter for search steps
		m_Steps = 0;
	}

	// Advances search one step 
	unsigned int SearchStep()
	{
		// Firstly break if the user has not initialised the search
		assert( (m_State > SEARCH_STATE_NOT_INITIALISED) &&
				(m_State < SEARCH_STATE_INVALID) );

		// Next I want it to be safe to do a searchstep once the search has succeeded...
		if( (m_State == SEARCH_STATE_SUCCEEDED) ||
			(m_State == SEARCH_STATE_FAILED) 
		  )
		{
			return m_State; 
		}

		// Failure is defined as emptying the open list as there is nothing left to 
		// search...
		// New: Allow user abort
		if( m_OpenList.empty() || m_CancelRequest )
		{
			FreeAllNodes();
			m_State = SEARCH_STATE_FAILED;
			return m_State;
		}
		
		// Incremement step count
		m_Steps ++;

		// Pop the best node (the one with the lowest f) 
		Node *n = m_OpenList.front(); // get pointer to the node
		pop_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() );
		m_OpenList.pop_back();

		// Check for the goal, once we pop that we're done
		if( n->m_UserState.IsGoal( m_Goal->m_UserState ) )
		{
			// The user is going to use the Goal Node he passed in 
			// so copy the parent pointer of n 
			m_Goal->parent = n->parent;

			// A special case is that the goal was passed in as the start state
			// so handle that here
			if( false == n->m_UserState.IsSameState( m_Start->m_UserState ) )
			{
				FreeNode( n );

				// set the child pointers in each node (except Goal which has no child)
				Node *nodeChild = m_Goal;
				Node *nodeParent = m_Goal->parent;

				do 
				{
					nodeParent->child = nodeChild;

					nodeChild = nodeParent;
					nodeParent = nodeParent->parent;
				
				} 
				while( nodeChild != m_Start ); // Start is always the first node by definition

			}

			// delete nodes that aren't needed for the solution
			FreeUnusedNodes();

			m_State = SEARCH_STATE_SUCCEEDED;

			return m_State;
		}
		else // not goal
		{

			// We now need to generate the successors of this node
			// The user helps us to do this, and we keep the new nodes in
			// m_Successors ...

			m_Successors.clear(); // empty vector of successor nodes to n

			// User provides this functions and uses AddSuccessor to add each successor of
			// node 'n' to m_Successors
			bool ret = n->m_UserState.GetSuccessors( this, n->parent ? &n->parent->m_UserState : NULL ); 

			if( !ret )
			{

			    typename vector< Node * >::iterator successor;

				// free the nodes that may previously have been added 
				for( successor = m_Successors.begin(); successor != m_Successors.end(); successor ++ )
				{
					FreeNode( (*successor) );
				}

				m_Successors.clear(); // empty vector of successor nodes to n

				// free up everything else we allocated
				FreeAllNodes();

				m_State = SEARCH_STATE_OUT_OF_MEMORY;
				return m_State;
			}
			
			// Now handle each successor to the current node ...
			for( typename vector< Node * >::iterator successor = m_Successors.begin(); successor != m_Successors.end(); successor ++ )
			{

				// 	The g value for this successor ...
				float newg = n->g + n->m_UserState.GetCost( (*successor)->m_UserState );

				// Now we need to find whether the node is on the open or closed lists
				// If it is but the node that is already on them is better (lower g)
				// then we can forget about this successor

				// First linear search of open list to find node

				typename vector< Node * >::iterator openlist_result;

				for( openlist_result = m_OpenList.begin(); openlist_result != m_OpenList.end(); openlist_result ++ )
				{
					if( (*openlist_result)->m_UserState.IsSameState( (*successor)->m_UserState ) )
					{
						break;					
					}
				}

				if( openlist_result != m_OpenList.end() )
				{

					// we found this state on open

					if( (*openlist_result)->g <= newg )
					{
						FreeNode( (*successor) );

						// the one on Open is cheaper than this one
						continue;
					}
				}

				typename vector< Node * >::iterator closedlist_result;

				for( closedlist_result = m_ClosedList.begin(); closedlist_result != m_ClosedList.end(); closedlist_result ++ )
				{
					if( (*closedlist_result)->m_UserState.IsSameState( (*successor)->m_UserState ) )
					{
						break;					
					}
				}

				if( closedlist_result != m_ClosedList.end() )
				{

					// we found this state on closed

					if( (*closedlist_result)->g <= newg )
					{
						// the one on Closed is cheaper than this one
						FreeNode( (*successor) );

						continue;
					}
				}

				// This node is the best node so far with this particular state
				// so lets keep it and set up its AStar specific data ...

				(*successor)->parent = n;
				(*successor)->g = newg;
				(*successor)->h = (*successor)->m_UserState.GoalDistanceEstimate( m_Goal->m_UserState );
				(*successor)->f = (*successor)->g + (*successor)->h;

				// Remove successor from closed if it was on it

				if( closedlist_result != m_ClosedList.end() )
				{
					// remove it from Closed
					FreeNode(  (*closedlist_result) ); 
					m_ClosedList.erase( closedlist_result );

					// Fix thanks to ...
					// Greg Douglas <gregdouglasmail@gmail.com>
					// who noticed that this code path was incorrect
					// Here we have found a new state which is already CLOSED
					// anus
					
				}

				// Update old version of this node
				if( openlist_result != m_OpenList.end() )
				{	   

					FreeNode( (*openlist_result) ); 
			   		m_OpenList.erase( openlist_result );

					// re-make the heap 
					// make_heap rather than sort_heap is an essential bug fix
					// thanks to Mike Ryynanen for pointing this out and then explaining
					// it in detail. sort_heap called on an invalid heap does not work
					make_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() );
			
				}

				// heap now unsorted
				m_OpenList.push_back( (*successor) );

				// sort back element into heap
				push_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() );

			}

			// push n onto Closed, as we have expanded it now

			m_ClosedList.push_back( n );

		} // end else (not goal so expand)

 		return m_State; // Succeeded bool is false at this point. 

	}

	// User calls this to add a successor to a list of successors
	// when expanding the search frontier
	bool AddSuccessor( UserState &State )
	{
		Node *node = AllocateNode();

		if( node )
		{
			node->m_UserState = State;

			m_Successors.push_back( node );

			return true;
		}

		return false;
	}

	// Free the solution nodes
	// This is done to clean up all used Node memory when you are done with the
	// search
	void FreeSolutionNodes()
	{
		Node *n = m_Start;

		if( m_Start->child )
		{
			do
			{
				Node *del = n;
				n = n->child;
				FreeNode( del );

				del = NULL;

			} while( n != m_Goal );

			FreeNode( n ); // Delete the goal

		}
		else
		{
			// if the start node is the solution we need to just delete the start and goal
			// nodes
			FreeNode( m_Start );
			FreeNode( m_Goal );
		}

	}

	// Functions for traversing the solution

	// Get start node
	UserState *GetSolutionStart()
	{
		m_CurrentSolutionNode = m_Start;
		if( m_Start )
		{
			return &m_Start->m_UserState;
		}
		else
		{
			return NULL;
		}
	}
	
	// Get next node
	UserState *GetSolutionNext()
	{
		if( m_CurrentSolutionNode )
		{
			if( m_CurrentSolutionNode->child )
			{

				Node *child = m_CurrentSolutionNode->child;

				m_CurrentSolutionNode = m_CurrentSolutionNode->child;

				return &child->m_UserState;
			}
		}

		return NULL;
	}
	
	// Get end node
	UserState *GetSolutionEnd()
	{
		m_CurrentSolutionNode = m_Goal;
		if( m_Goal )
		{
			return &m_Goal->m_UserState;
		}
		else
		{
			return NULL;
		}
	}
	
	// Step solution iterator backwards
	UserState *GetSolutionPrev()
	{
		if( m_CurrentSolutionNode )
		{
			if( m_CurrentSolutionNode->parent )
			{

				Node *parent = m_CurrentSolutionNode->parent;

				m_CurrentSolutionNode = m_CurrentSolutionNode->parent;

				return &parent->m_UserState;
			}
		}

		return NULL;
	}

	// For educational use and debugging it is useful to be able to view
	// the open and closed list at each step, here are two functions to allow that.

	UserState *GetOpenListStart()
	{
		float f,g,h;
		return GetOpenListStart( f,g,h );
	}

	UserState *GetOpenListStart( float &f, float &g, float &h )
	{
		iterDbgOpen = m_OpenList.begin();
		if( iterDbgOpen != m_OpenList.end() )
		{
			f = (*iterDbgOpen)->f;
			g = (*iterDbgOpen)->g;
			h = (*iterDbgOpen)->h;
			return &(*iterDbgOpen)->m_UserState;
		}

		return NULL;
	}

	UserState *GetOpenListNext()
	{
		float f,g,h;
		return GetOpenListNext( f,g,h );
	}

	UserState *GetOpenListNext( float &f, float &g, float &h )
	{
		iterDbgOpen++;
		if( iterDbgOpen != m_OpenList.end() )
		{
			f = (*iterDbgOpen)->f;
			g = (*iterDbgOpen)->g;
			h = (*iterDbgOpen)->h;
			return &(*iterDbgOpen)->m_UserState;
		}

		return NULL;
	}

	UserState *GetClosedListStart()
	{
		float f,g,h;
		return GetClosedListStart( f,g,h );
	}

	UserState *GetClosedListStart( float &f, float &g, float &h )
	{
		iterDbgClosed = m_ClosedList.begin();
		if( iterDbgClosed != m_ClosedList.end() )
		{
			f = (*iterDbgClosed)->f;
			g = (*iterDbgClosed)->g;
			h = (*iterDbgClosed)->h;

			return &(*iterDbgClosed)->m_UserState;
		}

		return NULL;
	}

	UserState *GetClosedListNext()
	{
		float f,g,h;
		return GetClosedListNext( f,g,h );
	}

	UserState *GetClosedListNext( float &f, float &g, float &h )
	{
		iterDbgClosed++;
		if( iterDbgClosed != m_ClosedList.end() )
		{
			f = (*iterDbgClosed)->f;
			g = (*iterDbgClosed)->g;
			h = (*iterDbgClosed)->h;

			return &(*iterDbgClosed)->m_UserState;
		}

		return NULL;
	}

	// Get the number of steps

	int GetStepCount() { return m_Steps; }

	void EnsureMemoryFreed()
	{
#if USE_FSA_MEMORY
		assert(m_AllocateNodeCount == 0);
#endif

	}

private: // methods

	// This is called when a search fails or is cancelled to free all used
	// memory 
	void FreeAllNodes()
	{
		// iterate open list and delete all nodes
		typename vector< Node * >::iterator iterOpen = m_OpenList.begin();

		while( iterOpen != m_OpenList.end() )
		{
			Node *n = (*iterOpen);
			FreeNode( n );

			iterOpen ++;
		}

		m_OpenList.clear();

		// iterate closed list and delete unused nodes
		typename vector< Node * >::iterator iterClosed;

		for( iterClosed = m_ClosedList.begin(); iterClosed != m_ClosedList.end(); iterClosed ++ )
		{
			Node *n = (*iterClosed);
			FreeNode( n );
		}

		m_ClosedList.clear();

		// delete the goal

		FreeNode(m_Goal);
	}


	// This call is made by the search class when the search ends. A lot of nodes may be
	// created that are still present when the search ends. They will be deleted by this 
	// routine once the search ends
	void FreeUnusedNodes()
	{
		// iterate open list and delete unused nodes
		typename vector< Node * >::iterator iterOpen = m_OpenList.begin();

		while( iterOpen != m_OpenList.end() )
		{
			Node *n = (*iterOpen);

			if( !n->child )
			{
				FreeNode( n );

				n = NULL;
			}

			iterOpen ++;
		}

		m_OpenList.clear();

		// iterate closed list and delete unused nodes
		typename vector< Node * >::iterator iterClosed;

		for( iterClosed = m_ClosedList.begin(); iterClosed != m_ClosedList.end(); iterClosed ++ )
		{
			Node *n = (*iterClosed);

			if( !n->child )
			{
				FreeNode( n );
				n = NULL;

			}
		}

		m_ClosedList.clear();

	}

	// Node memory management
	Node *AllocateNode()
	{

#if !USE_FSA_MEMORY
		Node *p = new Node;
		return p;
#else
		Node *address = m_FixedSizeAllocator.alloc();

		if( !address )
		{
			return NULL;
		}
		m_AllocateNodeCount ++;
		Node *p = new (address) Node;
		return p;
#endif
	}

	void FreeNode( Node *node )
	{

		m_AllocateNodeCount --;

#if !USE_FSA_MEMORY
		delete node;
#else
		m_FixedSizeAllocator.free( node );
#endif
	}

private: // data

	// Heap (simple vector but used as a heap, cf. Steve Rabin's game gems article)
	std::vector< Node *> m_OpenList;

	// Closed list is a vector.
	std::vector< Node * > m_ClosedList; 

	// Successors is a vector filled out by the user each type successors to a node
	// are generated
	std::vector< Node * > m_Successors;

	// State
	unsigned int m_State;

	// Counts steps
	int m_Steps;

	// Start and goal state pointers
	Node *m_Start;
	Node *m_Goal;

	Node *m_CurrentSolutionNode;

#if USE_FSA_MEMORY
	// Memory
 	FixedSizeAllocator<Node> m_FixedSizeAllocator;
#endif
	
	//Debug : need to keep these two iterators around
	// for the user Dbg functions
	typename std::vector< Node * >::iterator iterDbgOpen;
	typename std::vector< Node * >::iterator iterDbgClosed;

	// debugging : count memory allocation and free's
	int m_AllocateNodeCount;
	
	bool m_CancelRequest;

};



   
in the code above , the only thing im in doubt is where a function uses a operator overloading method inside a class...more specificly in the following:

Code: Select all

class HeapCompare_f 
	{
		public:

			bool operator() ( const Node *x, const Node *y ) const
			{
				return x->f > y->f;
			}
	};
so what does the above mean in practice?
and theres a couple more things im still in doubt which comes in the following code :

the file is a .cpp implementation file and holds the following code :

Code: Select all

//==========================================================================//
// Ogre A* Example - December 2009											//
//																			//
// Author: Daniel Soltyka													//
// E-Mail: dsoltyka@gmail.com												//
//																			//
// This example demonstrates the A* pathfinding algorithm in a 3D			// 
// environment.																//
//																			//
// Modified A* routines based off of A* Algorithm Implementation using STL	//
// by Justin Heyes-Jones.													//
//																			//
// Original Routines can be found at http://www.heyes-jones.com/astar.html	//
//==========================================================================//

#include "MapSearchNode.h"

MapSearchNode::MapSearchNode()
{ 
	x = y = 0; 
}

MapSearchNode::MapSearchNode( WorldMap* map ) 
{ 
	mMap = map; 
	x = y = 0;
}

MapSearchNode::MapSearchNode( WorldMap* map, unsigned int px, unsigned int py ) : mMap(map)
{ 
	x=px; 
	y=py; 
}	

// Compare this node against another node
bool MapSearchNode::IsSameState( MapSearchNode &rhs )
{
	// same state in a maze search is simply when (x,y) are the same
	if( (x == rhs.x) &&
		(y == rhs.y) )
	{
		return true;
	}
	else
	{
		return false;
	}
}

// Here's the heuristic function that estimates the distance from a Node
// to the Goal. 
float MapSearchNode::GoalDistanceEstimate( MapSearchNode &nodeGoal )
{
	float xd = fabs(float(((float)x - (float)nodeGoal.x)));
	float yd = fabs(float(((float)y - (float)nodeGoal.y)));

	return xd + yd;
}

// Test this node to see if it is the goal in our search
bool MapSearchNode::IsGoal( MapSearchNode &nodeGoal )
{

	if( (x == nodeGoal.x) &&
		(y == nodeGoal.y) )
	{
		return true;
	}

	return false;
}

// This generates the successors to the given Node. It uses a helper function called
// AddSuccessor to give the successors to the AStar class. The A* specific initialisation
// is done for each node internally, so here you just set the state information that
// is specific to the application
bool MapSearchNode::GetSuccessors( AStarSearch<MapSearchNode> *astarsearch, MapSearchNode *parent_node )
{
	int parent_x = -1; 
	int parent_y = -1; 

	if( parent_node )
	{
		parent_x = parent_node->x;
		parent_y = parent_node->y;
	}

	MapSearchNode NewNode;

	// push each possible move except allowing the search to go backwards

	if( (mMap->GetTile(x-1, y ) < 9) 
		&& !((parent_x == x-1) && (parent_y == y))
		) 
	{
		NewNode = MapSearchNode(mMap, x-1, y );
		astarsearch->AddSuccessor( NewNode );
	}	

	if( (mMap->GetTile(x, y-1 ) < 9) 
		&& !((parent_x == x) && (parent_y == y-1))
		) 
	{
		NewNode = MapSearchNode(mMap, x, y-1 );
		astarsearch->AddSuccessor( NewNode );
	}	

	if( (mMap->GetTile(x+1, y ) < 9)
		&& !((parent_x == x+1) && (parent_y == y))
		) 
	{
		NewNode = MapSearchNode(mMap, x+1, y );
		astarsearch->AddSuccessor( NewNode );
	}	


	if( (mMap->GetTile(x, y+1 ) < 9) 
		&& !((parent_x == x) && (parent_y == y+1))
		)
	{
		NewNode = MapSearchNode(mMap, x, y+1 );
		astarsearch->AddSuccessor( NewNode );
	}	

	return true;
}

// Given this node, what does it cost to move to successor. In the case
// of our map the answer is the map terrain value at this node since that is 
// conceptually where we're moving
float MapSearchNode::GetCost( MapSearchNode &successor )
{
	return (float) mMap->GetTile( x, y );

}


// Equal comparison between nodes
bool operator== (MapSearchNode &node1, MapSearchNode &node2)
{
    return ((node1.x == node2.x) && (node1.y == node2.y));
}

bool operator!= (MapSearchNode &node1, MapSearchNode &node2)
{
	return !(node1 == node2);
}
first off again another operator overloading method used in 2 different functions...which looks like this :

Code: Select all

bool operator== (MapSearchNode &node1, MapSearchNode &node2)
{
    return ((node1.x == node2.x) && (node1.y == node2.y));
}

bool operator!= (MapSearchNode &node1, MapSearchNode &node2)
{
	return !(node1 == node2);
what does it say in other words?

and also in the same implementation file there is a template type function and i wonder if all the functions in this file enherits this template data in the MapSearchNode class and parameters...coz here we have the getCost (),getSuccessors(),GoalDistanceEstimate() and IsSameState() functions which corresponds to the same names as in the AStarSearch class in its header file but most of them dont make reference to the stlastar.h file , so my question is , does this function arguments: bool MapSearchNode::GetSuccessors( AStarSearch<MapSearchNode> *astarsearch, MapSearchNode *parent_node )
{}
also assign to the MapSearchNode class parameters the AStarSearch class data for all these functions ? getCost (),getSuccessors(),GoalDistanceEstimate() and IsSameState()????
sorry if the question is a bit confusing but i tried my best to formulate what i have in mind at the moment...
thx in advance and any help is greatly appreciated!!!
kind regards,
Romulo Romero
Last edited by Blender+C++ on Fri May 04, 2012 11:33 pm, edited 1 time in total.
User avatar
Kojack
OGRE Moderator
OGRE Moderator
Posts: 7157
Joined: Sun Jan 25, 2004 7:35 am
Location: Brisbane, Australia
x 535

Re: doubt with Templates<> in A* implementation

Post by Kojack »

operator() is a way to treat a variable like a function.
In the code you listed, a variable of type HeapCompare_f can be called like a function, like this:

Code: Select all

HeapCompare_f myVar;
bool result = myVar(nodePtr1, nodePtr2);
So even though myVar is a normal class instance variable, you can pretend it's the name of a function.
There's no real need for it normally, it's just a nice compact syntax for calling a method of an object.

operator== lets you define how two objects are compared for equality. operator!= does the same for inequality.
In this case, operator== (MapSearchNode &node1, MapSearchNode &node2) is defining what happens when you try to test if two nodes are equal to each other. When C++ sees a == with user classes on one or both sides, it looks for an operator== that has matching argument types. So in this code it is saying what to do if you ever have == with a MapSearchNode on both sides (node1 is the left hand side, node2 is the right hand side).
You could use it like this:

Code: Select all

MapSearchNode node1;
MapSearchNode node2;
// do stuff with the nodes here. This is just an example.
if(node1 == node2)
{
   // they are equal (the same x and y coordinates)
}
operator!= is doing the same thing, it's just returning the not (opposite) of the operator==.

There's a ton of operators you can overload in C++, they make it easier to use classes by making them seem like built in types.
Blender+C++
Gremlin
Posts: 171
Joined: Tue Jan 03, 2012 1:38 am
Location: Brazil
x 3

Re: doubt with Templates<> in A* implementation

Post by Blender+C++ »

Hi Kojack,
first of all thanks a lot for the fast reply dude,
and if i tell u something ur gonna say that im a liar but im serious dude, i am not lieing ^^ , in the first explanation and the other two ,before u post it i was kind of correct with my reasoning based on what i have researched bout the the operators overloading and i also know that some operators cant be overloaded , such as :: , sizeOf and some others that i dont remember but it was a big help ur detailed explanations, that ensured me that it was right the way i thought those functions were trying to say..ANYWAYS if it wasnt you i would never know how it exactly works sooo..thx alot for that..buuuttt..there s still a remaining question which is the last one, i dont know if im asking too much but it would be so kind of u, if u clarify the function which has a template data, considering that most of the functions in that .cpp file have the same names as in the stlastar.h file (which corresponds to the AStarSearch class), i want to know if the template argument in this function : GetSuccessors( AStarSearch<MapSearchNode> *astarsearch, MapSearchNode *parent_node )
also assigns the other functions in the MapSearchNode.cpp with the same names as in the AStarSeach class with the template data for <MapSearchNode> in the arguments inside these functions : getCost (),getSuccessors()(with this one i know coz it refers to the AStarSearch class but what bout the others? it would make much sense if they are also part of the template data),GoalDistanceEstimate() and IsSameState() ????

yeah i know i cant express myself but as i said im trying my best...
again any help is greatly appreciated!!!
kind regards,
Romulo Romero
EDIT: i edited this post over 100 times lol...just a side comment hehe
Blender+C++
Gremlin
Posts: 171
Joined: Tue Jan 03, 2012 1:38 am
Location: Brazil
x 3

Re: doubt with Templates<> in A* implementation

Post by Blender+C++ »

Ok well..maybe i got the answer? so i just need a confirmation from any of you guys..
hmm in this sample we have also a class header file and a .cpp file named PathFinder...and in the class we have a private member var which looks like this : AStarSearch<MapSearchNode> mAStarSearch; and its used inside a lot of functions,not to say in almost all of them...by hovering the mouse over some stuff i can kind of see whats going on an whats linked to what...
so by that i assume that everything inside the AStarSearch class template data(which is the UserState if u look at the stlastar.h file) also corresponds to the MapSearchNode class functions data? so all the functions inside the MapSearchNode.cpp which contains the same names as in the AStarSearch class are linked to the stlastar.h file(AStarSearch class and others) functions and data?
i hope that the text above is clear enuff for u guys to understand my point!
thx in advance for any answer...
kind regards,
Romulo Romero
Blender+C++
Gremlin
Posts: 171
Joined: Tue Jan 03, 2012 1:38 am
Location: Brazil
x 3

Re: doubt with Templates<> in A* implementation

Post by Blender+C++ »

allright , i think i might've asked too much for help and maybe i hit the bulls eye and am overlookin it so thx guys!
SOLVED