Recursion without parameters, nor static or global variables - c++

I was given a homework that asked me to iterate through a linked list with a given class header which I should not change:
template<typename ItemType>
class LinkedList{
public:
...
LinkedList();
LinkedList(const LinkedList<ItemType>&);
int getCurrentSize340RecursiveNoHelper() const;
private:
Node<ItemType>* headPtr{ nullptr }; // Pointer to first node
}
The node class header is:
template<typename ItemType>
class Node {
public:
...
Node();
Node(const ItemType&);
Node(const ItemType&, Node<ItemType>*);
Node<ItemType>* getNext() const;
private:
ItemType item; // A data item
Node<ItemType>* next{ nullptr }; // Pointer to next node
}
In the function getCurrentSize340RecursiveNoHelper(), we are supposed to iterate the linked list to get the size.
I know that I could iterate the linked list with the help of static or global, but my professor says that we should avoid using them. Is there any possible way to do that?

You can recurse through member variables rather than parameters.
int LinkedList::getCurrentSize340RecursiveNoHelper() const {
if (this->headPtr == nullptr){
return 0;
}
Node<ItemType> nextNode = this->headPtr->getNext();
if (nextNode != nullptr){
LinkedList<ItemType> restOfList;
restOfList.add(nextNode); // a bit weird but this is the only way you can set the headPtr of a linked list.
return 1 + restOfList.getCurrentSize340RecursiveNoHelper();
}
return 1;
}

In the function getCurrentSize340RecursiveNoHelper(), we are supposed
to iterate the linked list to get the size.
I know that I could iterate the linked list with the help of static or
global, but my professor says that we should avoid using them.
Is there any possible way to do that?
Last question first: YES, this is possible, even easy. Software is remarkably flexible.
Recursion without function parameters (nor static vars, nor global vars).
Iteration and recursion without parameters are both easy to do, once you've seen how.
And with practice, you can easily avoid both static and global vars.
See also: https://stackoverflow.com/a/45550373/2785528, which presents a simple mechanism to "pass user input through a system without using global vars". We might summarize it into 2 steps, a) early in main instantiate a custom class instance to contain (for 'transport') any user inputs / values that you would otherwise place into global vars for the various users to fetch, and then b) pass these transport objects by reference to the ctors of objects that need them (in similar fashion to a travel case). Easy.
Kudo's to the professor to insist on user-defined-types (UDT). This is the stuff you need to practice on.
However, for this post, it will be simpler to study the how-to (of iteration and recursion without parameters, etc.) by simply ignoring the UDT with which you stated no problems. In this way, we can concentrate on the function forms.
To simplify even more, my examples will be Functors ... a short and simple form of classes. I recommend Functor classes as both simple and efficient.
And one more simplification, I will use std::list. There are plenty of examples of how to make, fill, and use this container.
One key idea (to support no-parameter-functions) is to 'bundle' your data and methods into the class. Encapsulation is your friend.
Idea 1 -- Minimize main(). Keep it short. Get out and direct to business.
int main(int, char**)
{
int retVal = 0;
retVal += F820_Iterative_t()();
retVal += F820_Recursive_t()();
return retVal;
}
Here, two functors are invoked. I separated the iterative from recursive examples.
Note that these functors are invoked early in main. There are many things that get initialized before main (but see the well known initialization fiasco). This simplifies and controls when these init's happen.
The first functor will instantiate, process, then destruct, completing its full lifetime before the next functor gets started, i.e. they are serialized.
data types:
// examples use std::list
// user typedefs ---------------vvvvvvvvvvv
typedef list<string> StrList_t;
typedef list<string>::iterator StrListIt_t;
data attributes:
// Functor
class F820_Iterative_t
{
// NOTE: class instance data attributes are not global vars
StrList_t m_strList; // std::list<std::string>
StrListIt_t m_it; // std::list<std::string>::iterator
...
// Functor
class F820_Recursive_t
{
StrList_t m_strList; // std::list<std::string>
StrListIt_t m_it; // std::list<std::string>::iterator
...
Example 1 -- iterative element count
// iterate with no parameters, static vars, or global vars
uint F820_Iterative_t::iterateCount( )
{ // --^-- no params
uint lcount = 0;
do // -------------iterative loop
{
if (m_it == m_strList.end()) // detect end of list
break; // kick out
lcount += 1;
m_it++; // step to next element
} while(true);
return(lcount);
}
Example 2 -- recursive element count
// recurse with no parameters, static vars, or global vars
uint F820_Recursion_t::recurseCount( )
{ // --^-- no params
if (m_it == m_strList.end()) // RTC (recursion termination clause)
return 0;
m_it++; // step to next element
return (1 + recurseCount()); // tail recursion
} // --^^^^^^^^^^^^-- recursive invocation
In both of the above element count functions, the Functor data attributes are initialized before F820_xxx::xxxCount() is invoked.
This code uses no function parameters, and no global vars. The vars used in these funcs (m_it and m_strList) are data attributes of the class instance. The function access them directly through the implied 'this' pointer.
Life interrupts.
Both xxxxCount() are above for comparison. Ask for more if you want, this code compiles and runs. I plan to find time to insert the rest.

When you're dealing with recursive problems, a trick is to just assume that the recursive function works if and only if you give it a simpler problem to work on than the one you're dealing with. You're given a pointer to the head of the linked list. After you've dealt with the base case, you now know that the list has at least one element. A simpler problem you can ask your recusive function to do is to calculate the length of the rest of the list and then just add 1 to the result.

Related

Remove related object from list C++

I have some code:
class LowLevelObject {
public:
void* variable;
};
// internal, can't get access, erase, push. just exists somewhere
std::list<LowLevelObject*> low_level_objects_list;
class HighLevelObject {
public:
LowLevelObject* low_level_object;
};
// my list of objects
std::list<HighLevelObject*> high_level_objects_list;
// some callback which notifies that LowLevelObject* added to low_level_objects_list.
void CallbackAttachLowLevelObject(LowLevelObject* low_level_object) {
HighLevelObject* high_level_object = new HighLevelObject;
high_level_object->low_level_object = low_level_object;
low_level_object->variable = high_level_object;
high_level_objects_list.push_back(high_level_object);
}
void CallbackDetachLowLevelObject(LowLevelObject* low_level_object) {
// how to delete my HighLevelObject* from high_level_objects_list?
// HighLevelObject* address in field `variable` of LowLevelObject.
}
I have low level object which defined in library, it contains field variable for using by user.
I set to this varaible pointer to my HighLevelObject from my code.
I can set callbacks on add and remove LowLevelObject from list in library.
But how can I remove my HighLevelObject from my list of objects?
Of course, I know that I can iterate whole list and find by object by pointer and remove, but it's long way.
List may contains a lot of objects.
Thanks in advance!
The setup lends itself to finding a solution where converting a pointer to an iterator is a constant-time operation. Boost.Intrusive offers this feature. This will require changes to your code though; if you were not careful about encapsulation, these changes might be significant. A boost::intrusive::list is functionally similar to a std::list, but requires some changes to your data structure. This option might not be for everyone.
Another feature of Boost.Intrusive is that sometimes you do not need to explicitly convert a pointer to an iterator. If you enable auto-unlinking, then the actual deletion from the list happens behind the scenes in a destructor. This is not a good option if you need to get the size of your list in constant time, though. (Nothing in the question indicates that getting the size of the list is needed, so I'll go ahead with this approach.)
If you had a container of objects, I might let you work through the documentation for the intrusive list. However, your use of pointers makes the conversion potentially confusing, so I'll walk through the setup. The setup begins with the following.
#include <boost/intrusive/list.hpp>
// Shorten the needed boost namespace.
namespace bi = boost::intrusive;
Since the list of high-level objects contains pointers, an auxiliary structure is needed. We need what amounts to a pointer that derives from a class provided by Boost. (I will proceed assuming that the objects created in CallbackAttachLowLevelObject() must be destroyed in CallbackDetachLowLevelObject(). Hence, I've changed the raw pointer to a smart pointer.)
#include <memory>
#include <utility>
// The auxiliary structure that will be stored in the high level list:
// The hook supplies the intrusive infrastructure.
// The link_mode enables auto-unlinking.
class ListEntry : public bi::list_base_hook< bi::link_mode<bi::auto_unlink> >
{
public:
// The expected way to construct this.
explicit ListEntry(std::unique_ptr<HighLevelObject> && p) : ptr(std::move(p)) {}
// Another option would be to forward parameters for constructing HighLevelObject,
// and have the constructor call make_unique. I'll leave that as an exercise.
// Make this class look like a pointer to HighLevelObject.
const std::unique_ptr<HighLevelObject> & operator->() const { return ptr; }
HighLevelObject& operator*() const { return *ptr; }
private:
std::unique_ptr<HighLevelObject> ptr;
};
The definition of the list becomes the following. We need to specify non-constant time size() to allow auto-unlinking.
bi::list<ListEntry, bi::constant_time_size<false>> high_level_objects_list;
These changes require some changes to the "attach" callback. I'll present them before going on to the "detach" callback.
// Callback that notifies when LowLevelObject* is added to low_level_objects_list.
void CallbackAttachLowLevelObject(LowLevelObject* low_level_object) {
// Dynamically allocate the entry, in addition to allocating the high level object.
ListEntry * entry = new ListEntry(std::make_unique<HighLevelObject>());
(*entry)->low_level_object = low_level_object; // Double indirection needed here.
low_level_object->variable = entry;
high_level_objects_list.push_back(*entry); // Intentional indirection here!
}
With this prep work, the cleanup is in your destructors, as is appropriate for RAII. Your "detach" just has to initiate the process. One line suffices.
void CallbackDetachLowLevelObject(LowLevelObject* low_level_object) {
delete static_cast<ListEntry *>(low_level_object->variable);
}
There (appropriately) is not enough context in the question to explain why the high level list is of pointers instead of being of objects. One potential reason is that the high-level object is polymorphic, and the use of pointers avoids slicing. If this is the case (or if there is not a good reason for using pointers), an intrusive list could be designed with less impact on existing code. The caveat here is that changes to HighLevelObject are required.
The initial setup is the same as before.
#include <boost/intrusive/list.hpp>
// Shorten the needed boost namespace.
namespace bi = boost::intrusive;
Next, have HighLevelObject derive from the hook.
class HighLevelObject : public bi::list_base_hook< bi::link_mode<bi::auto_unlink> > {
public:
LowLevelObject* low_level_object;
};
In this situation, the list is of HighLevelObjects, not of pointers, nor of pointer stand-ins.
bi::list<HighLevelObject, bi::constant_time_size<false>> high_level_objects_list;
The "attach" callback reverts to almost what is in the question. The one change to this function is that the object itself is pushed into the list, not a pointer. This is why slicing is not a problem; it's not a copy that is added to the list, but the object itself.
high_level_objects_list.push_back(*high_level_object); // Intentional indirection!
The rest of your code might work as-is. We just need the "detach" callback, which again is a one-liner.
void CallbackDetachLowLevelObject(LowLevelObject* low_level_object) {
delete static_cast<HighLevelObject *>(low_level_object->variable);
}
This answer is for those who do not want to use – or cannot use – Boost.Intrusive.
As long as modifying HighLevelObject is an option, the object could be told how to remove itself from the list. Add a callback to HighLevelObject and invoke it in its destructor.
#include <functional>
#include <utility>
class HighLevelObject {
public:
LowLevelObject* low_level_object;
// ****** The above is from the question. The below is new. ******
// Have the destructor invoke the callback.
~HighLevelObject() { if ( on_delete ) on_delete(); }
// Provide a way to set the callback.
void set_deleter(std::function<void()> && deleter)
{ on_delete = std::move(deleter); }
private:
// Storage for the callback:
std::function<void()> on_delete;
};
Set the callback when an object is added to the high level list.
Caution: This setup supports only one callback. Don't overwrite the callback somewhere else in your code!
Caution: Additional precautions are needed if multiple threads might add elements to high_level_objects_list.
// Callback that notifies when LowLevelObject* is added to low_level_objects_list.
void CallbackAttachLowLevelObject(LowLevelObject* low_level_object) {
HighLevelObject* high_level_object = new HighLevelObject;
high_level_object->low_level_object = low_level_object;
low_level_object->variable = high_level_object;
high_level_objects_list.push_back(high_level_object);
// ****** The above is from the question. The below is new. ******
// Arrange cleanup.
auto iter = high_level_objects_list.end(); // Not thread-safe
high_level_object->set_deleter([iter]() { high_level_objects_list.erase(iter); });
}
With this prep work, the cleanup is in your destructor, as is appropriate for RAII. Your "detach" just has to initiate the process. One line suffices.
void CallbackDetachLowLevelObject(LowLevelObject* low_level_object) {
delete static_cast<HighLevelObject *>(low_level_object->variable);
}
I was thinking of storing an iterator (specifically, iter in the above) in HighLevelObject and having the destructor use that to call erase() instead of going through a lambda. However, I ran into trouble with the declarations, since members of std::list cannot be instantiated with an incomplete element type. It could be done with type erasure, but at that point I preferred using a function object.

C++ design choice

There is a class ActionSelection which has the following method:
ActionBase* SelectAction(Table* table, State* state);
ActionBase is an abstract class. Inside of the SelectAction method some action is fetched from the table considering the state if the table is not empty.
If the table is empty, a random action should be created and returned. However ActionBase is an abstract class, so can not be instantiated.
For different experiments/environments actions are different but have some common behavior (that's why there is an ActionBase class)
The problem is that this function (SelectAction) should return an experiment specific action, if the table is empty, however it does not know anything about the specific experiment. Are there any design workarounds of this?
It depends on whether empty tables...
Are expected to happen under normal circumstances
May happen under abnormal circumstances
Should never happen unless there is a bug in the program
Solution 1:
Include empty table handling into your control flow. As-is the function does not have enough information to react properly, so either :
Pass in a third parameter, containing a default action to return :
ActionBase *SelectAction(Table *table, State *state, ActionBase *defaultAction);
If you don't want to construct the default action unless it's needed, you can pass its type via a template parameter instead, optionally with additional parameters to construct it with :
template <class DefaultAction, class... DefActArgs>
ActionBase *SelectAction(Table *table, State *state, DefActArgs &&... args);
Let the caller handle it, by returning whether or not the operation was successful :
bool SelectAction(Table *table, State *state, ActionBase *&selectedAction);
Solution 2:
Throw an exception. It will bubble up to whoever can handle it. This is quite rarely used as a parameter check, since it should have been thrown by the object that should have produced a non-empty table in the first place.
ActionBase *SelectAction(Table *table, State *state) {
if(table->empty())
throw EmptyTableException();
// ...
}
Solution 3:
Setup an assertion. If your function received an empty table, something is broken, better halt the program and have a look at it with a debugger.
ActionBase *SelectAction(Table *table, State *state) {
assert(!table->empty());
// ...
}
Here is what I had in mind : It is not tested code but you get the idea.
1.
//header
class RandomActionBase : public ActionBase{
public
RandomActionBase();
static RandomAction* selectRandomAction();
protected:
static RandomActionBase* _first;
RandomActionBase* _next;
void register(RandomActionBase* r);
};
//implementation
RandomActionBase::_first = NULL;
RandomActionBase::RandomActionBase():_next(NULL){
if (_first==NULL) _first = this;
else _first->register(this);
}
void RandomActionBase::register(RandomActionBase* r)
{
if (_next==NULL) _next = r;
else _next->register(r);
}
RandomAction* RandomActionBase::selectRandomAction()
{
//count the number of randomactionbases
int count = 0;
RandomActionBase* p = _first;
while(p){
++count;
p = p->_next;
}
//now that you know the count you can create a random number ranging from 0 to count, I 'll leave this up to you and assume the random number is simply 2,
unsigned int randomnbr = 2;
RandomActionBase* p = _first;
while(randomnbr>0){
p= p->_next;
--randomnbr;
}
return p;
}
//header
class SomeRandomAction : public RandomActionBase{
public:
//implement the custom somerandomaction
}
//implementation
static SomeRandomAction SomeRandomAction_l;
The idea of course is to create different implementations of SomeRandomAction or even to pass parameters to them via their constructor to make them all distinct. For each instance you create they will appear in the static list.
Extending the list with a new imlementation just means to derive from RandomActionBase , implement it and make sure to create an instance, the base class is never impacted by this which make it even a design according to OCP.
Open closed principle. The code is extendable while not having to change the code that is already in place. OCP is part of SOLID.
2.
Another viable solution is to return a null object. It is quite similar as above but you always return the null object when the list is empty. Mind you a null object is not simply null. See https://en.wikipedia.org/wiki/Null_Object_pattern
It is simply a dummy implementation of a class to avoid having to check for null pointers to make the design more elegant and less susceptible for null pointer dereferencing errors.

How to create method which will know that its instance is in matrix of another class

I'm an absolute beginner in OOP (and C++). Trying to teach myself using resources my university offers for students of higher years, and a bunch of internet stuff I can find to clear things up.
I know basic things about OOP - I get the whole point of abstracting stuff into classes and using them to create objects, I know how inheritance works (at least, probably the basics), I know how to create operator functions (although as far as I can see that only helps in code readability in a sense that it becomes more standard, more language like), templates, and stuff like that.
So I've tried my first "project": to code Minesweeper (in command line, I never created a GUI before). Took me a few hours to create the program, and it works as desired, but I feel like I'm missing a huge point of OOP in there.
I've got a class "Field" with two attributes, a Boolean mine and a character forShow. I've defined the default constructor for it to initialize an instance as an empty field (mine is false), and forShowis . (indicating a not yet opened filed). I've got some simple inline functions such as isMine, addMine, removeMine, setForShow, getForShow, etc.
Then I've got the class Minesweeper. Its attributes are numberOfColumns, ~ofRows, numberOfMines, a pointer ptrGrid of type Mine*, and numberOfOpenedFields. I've got some obvious methods such as generateGrid, printGrid, printMines (for testing purposes).
The main thingy about it is a function openFiled which writes the number of mines surrounding the opened field, and another function clickField which recursively calls itself for surrounding fields if the field which is currently being opened has 0 neighbor mines. However, those two functions take an argument -- the index of the field in question. That kinda misses the point of OOP, if I understand it correctly.
For example, to call the function for the field right to the current one, I have to call it with argument i+1. The moment I noticed this, I wanted to make a function in my Field class which would return a pointer to the number right to it... but for the class Field itself, there is no matrix, so I can't do it!
Is it even possible to do it, is it too hard for my current knowledge? Or is there another more OOP-ish way to implement it?
TLDR version:
It's a noob's implemetation of Minesweeper game using C++. I got a class Minesweeper and Field. Minesweeper has a pointer to matrix of Fields, but the navigation through fields (going one up, down, wherever) doesn't seem OOP-ishly.
I want to do something like the following:
game->(ptrMatrix + i)->field.down().open(); // this
game->(ptrMatrix + i + game.numberOfColumns).open(); // instead of this
game->(ptrMatrix + i)->field.up().right().open(); // this
game->(ptrMatrix + i + 1 - game.numberOfColumns).open(); // instead of this
There are a couple of ways that you could do this in an OOP-ish manner. #Peter Schneider has provided one such way: have each cell know about its neighbours.
The real root of the problem is that you're using a dictionary (mapping exact coordinates to objects), when you want both dictionary-style lookups as well as neighbouring lookups. I personally wouldn't use "plain" OOP in this situation, I'd use templates.
/* Wrapper class. Instead of passing around (x,y) pairs everywhere as two
separate arguments, make this into a single index. */
class Position {
private:
int m_x, m_y;
public:
Position(int x, int y) : m_x(x), m_y(y) {}
// Getters and setters -- what could possibly be more OOPy?
int x() const { return m_x; }
int y() const { return m_y; }
};
// Stubbed, but these are the objects that we're querying for.
class Field {
public:
// don't have to use an operator here, in fact you probably shouldn't . . .
// ... I just did it because I felt like it. No justification here, move along.
operator Position() const {
// ... however you want to get the position
// Probably want the Fields to "know" their own location.
return Position(-1,-1);
}
};
// This is another kind of query. For obvious reasons, we want to be able to query for
// fields by Position (the user clicked on some grid), but we also would like to look
// things up by relative position (is the cell to the lower left revealed/a mine?)
// This represents a Position with respect to a new origin (a Field).
class RelativePosition {
private:
Field *m_to;
int m_xd, m_yd;
public:
RelativePosition(Field *to, int xd, int yd) : m_to(to), m_xd(xd),
m_yd(yd) {}
Field *to() const { return m_to; }
int xd() const { return m_xd; }
int yd() const { return m_yd; }
};
// The ultimate storage/owner of all Fields, that will be manipulated externally by
// querying its contents.
class Minefield {
private:
Field **m_field;
public:
Minefield(int w, int h) {
m_field = new Field*[w];
for(int x = 0; x < w; x ++) {
m_field[w] = new Field[h];
}
}
~Minefield() {
// cleanup
}
Field *get(int x, int y) const {
// TODO: check bounds etc.
// NOTE: equivalent to &m_field[x][y], but cleaner IMO.
return m_field[x] + y;
}
};
// The Query class! This is where the interesting stuff happens.
class Query {
public:
// Generic function that will be instantiated in a bit.
template<typename Param>
static Field *lookup(const Minefield &field, const Param &param);
};
// This one's straightforwards . . .
template<>
Field *Query::lookup<Position>(const Minefield &field, const Position &pos) {
return field.get(pos.x(), pos.y());
}
// This one, on the other hand, needs some precomputation.
template<>
Field *Query::lookup<RelativePosition>(const Minefield &field,
const RelativePosition &pos) {
Position base = *pos.to();
return field.get(
base.x() + pos.xd(),
base.y() + pos.yd());
}
int main() {
Minefield field(5,5);
Field *f1 = Query::lookup(field, Position(1,1));
Field *f0 = Query::lookup(field, RelativePosition(f1, -1, -1));
return 0;
}
There are a couple of reasons why you might want to do it this way, even if it is complicated.
Decoupling the whole "get by position" idea from the "get neighbour" idea. As mentioned, these are fundamentally different, so expose a different interface.
Doing it in this manner gives you the opportunity to expand later with more Query types in a straightforwards fashion.
You get the advantage of being able to "store" a Query for later use. Perhaps to be executed in a different thread if it's a really expensive query, or in an event loop to be processed after other events, or . . . lots of reasons why you might want to do this.
You end up with something like this: (C++11 ahead, be warned!)
std::function<Field *()> f = std::bind(Query::lookup<RelativePosition>,
field, RelativePosition(f1, -1, -1));
. . . wait, what?
Well, what we essentially want to do here is "delay" an execution of Query::lookup(field, RelativePosition(f1, -1, -1)) for later. Or, rather, we want to "set up" such a call, but not actually execute it.
Let's start with f. What is f? Well, by staring at the type signature, it appears to be a function of some sort, with signature Field *(). How can a variable be a function? Well, it's actually more like a function pointer. (There are good reasons why not to call it a function pointer, but that's getting ahead of ourselves here.)
In fact, f can be assigned to anything that, when called, produces a Field * -- not just a function. If you overload the operator () on a class, that's a perfectly valid thing for it to accept as well.
Why do we want to produce a Field * with no arguments? Well, that's an execution of the query, isn't it? But the function Query::lookup<RelativePosition> takes two arguments, right?
That's where std::bind comes in. std::bind essentially takes an n-argument function and turns it into an m-argument function, with m <= n. So the std::bind call takes in a two-place function (in this case), and then fixes its first two arguments, leaving us with . . .
. . . a zero-argument function, that returns a Field *.
And so we can pass around this "function pointer" to a different thread to be executed there, store it for later use, or even just repeatedly call it for kicks, and if the Position of Fields was to magically change for some reason (not applicable in this situation), the result of calling f() will dynamically update.
So now that I've turned a 2D array lookup into a mess of templates . . . we have to ask a question: is it worth it? I know this is a learning exercise and all, but my response: sometimes, an array is really just an array.
You can link the four neighbours to the cell via pointers or references. That would likely happen after the playing field has been created. Whether that's good or bad design I'm not sure (I see the same charme though that you see). For large fields it would increase the memory footprint substantially, because a cell probably doesn't hold that much data besides these pointers:
class Cell
{
// "real" data
Cell *left, *right, *upper, *lower;
// and diagonals? Perhaps name them N, NE, E, SE, S...
};
void init()
{
// allocate etc...
// pseudo code
foreach r: row
{
foreach c: column
{
// bounds check ok
cells[r][c].upper = &cells[r-1][c];
cells[r][c].left = &cells[r][c-1];
// etc.
}
}
// other stuff
}

Accomplish this task in C++; Migration from AS3.0

I've got way too much information to work with, so for now I'll consider this question answered until I can sort it all out and decide on the final implementation! Thanks a ton gf and Simon Buchan. I wish I could accept both of your answers, since they're both definite possibilities!
Additional / Revised Conceptual Information as suggested:
What I am aiming to do;
I am making a game. In this game every object used is an instance of the DOBJ class. The TUR class extends the DOBJ class. The SHO class extends the TUR class.
Each TUR class has an array of SHO's stored in it's SHOARR array. Each SHO instance needs to be given a set of instructions.
I know for a fact I could make 1000's of different SHO classes that have their instructions set during construction.
However, considering I will have so many different acting SHO instances, I was interested in another way to pass a set of instructions. Through the contruction of the SHO would be the ideal.
The instructions I am attempting to pass to each SHO are simple if statements;
if(frame > 64) { rotation += 4; };
if(state == 0 && frame < 32) { xs = 12; ys = 12; state = 1; };
Original question
Migration from ActionScript3.0 to C++ is proving to be a trial indeed. Thanks to those who have answered my questions thus far and also to those who opened stackoverflow in the first place. Onto the question... (TL;DR near the bottom to get straight to the question)
I'm attempting to apply the same logic that I could apply in AS3.0 to my project in C++ and it's just not going very well.
In AS3.0 I was used to slapping any and every datatype into an Array. It made things pretty simple. Now that I've run into C++ dev, I realized that I can't exactly do that anymore.
So now I'm stuck with this problem of rewriting a little AI system in a new language, where the driving point of the system isn't even compatible!
Here's an example of a piece of the code I was writing in AS3.0;
AI[NUM][1]( OBJ, AI[NUM][2], AI[NUM][3] );
AI being an array, NUM being an integer, OBJ being an instance of a class.
This line obviously called the function in the second element of the first array in the main array with the arguments being a class in which to perform the function on, whatever was in the third element of the first array of the main array, and likewise the fourth element.
In this case;
AI[NUM][1] would be a function
AI[NUM][2] would be a variable
AI[NUM][3] would be a number
Generally, my AI was run on calling a function to change or compare the variable with a number.
An example would be;
CompareST( someObject, "x", 500 );
and return true if someObject's x variable was smaller than (ST) 500.
The AI array itself was just filled with arrays of calls similar to this.
Quite new to C++ I had no idea how to go about this, so I did a bit of searching and reading of many different websites and came to the conclusion that I should look into function pointers.
However, after reading a bit into them, I've come to the conclusion that it won't help me realize my goal. While it did help me call functions like I wanted to call them, it doesn't help me stack different datatypes into one large array of arrays.
TL;DR
EDIT++:
What I need for each object is a set of instructions to be checked every frame. However, for each instance of the class, the instructions have to be different.
I plan on having a LOT of different instances, so making a class for each one is unreasonable.
Thus, I needed a way to pass a set of instructions to each one through it's constructor and read + execute them at any time their think() function is called.
My ultimate goal (aside from finding out about a better way to go about this) would be to be able to have an array of function calls, like;
A[n][0]( O, A[n][1], A[n][2] );
Where;
O is the instance the function is altering
A[n][0] is a function (Equality or Comparison)
A[n][1] is the variable, eg; "x", O["x"] (or a pointer to that variable in the case of C++)
A[n][2] is the value to alter the variable by, or compare it to.
And I'm not sure how I would rewrite this into C++, or alter it to work in another way.
Aftermath / Additional Information
What I'm actually aiming to do is be able to give an object a set of instructions at the time of it's creation, through the constructor. For example upon creation give an object instructions to wait 64 frames, and then rotate in the opposite direction, would have been something like this;
t.AI = [ [ 1, AIF.CompareET, "STATE", 0, AIF.CompareGT, "FRAME", 64, 0, AIF.EqualityAT, "baseRotation", 180, AIF.EqualityET, "STATE", 1 ] ];
In pseudocode;
(The 1 in the array denotes how to read the rest of the array, in this case everything before the odd 0 [ The one that comes after 64 ] is a comparison. If any of those fail, anything after the 0 will not be looked at )
Compare STATE is equal to (ET) 0, if true
Compare FRAME is greather than (GT) 64, if true
Add 180 to (AT) baseRotation, Set STATE equal to 1
Sorry that this turned out really long. I hope it's understandable, and I'm not asking something stupidly difficult to explain.
You can store functions using function pointers or functors. Variant types though are not natively supported by C++, you have to use custom solutions there.
One possibility would be to use Boost.Any (or better, Boost.Variant if you only use a fixed set of types):
typedef void (*Function)(Object*, const std::string&, boost::any&);
std::vector<Function> functions;
Given some function:
void f(Object* obj, const std::string& name, boost::any& value) {
// ...
}
you could store and call it similar to your example:
functions.push_back(&f);
functions[0](obj, "x", boost::any(500));
To utilize a declarative syntax, there are three options that come to my mind:
you use a similar approach and have central "interpreter" function, e.g. based on a switch (don't forget to switch to integers or pointers-to-members instead of strings if you need performance)
you invent your own language and generate C++ code from description files
you compose function objects in a declarative way
To do composition, you could use Boost.Bind or something like custom objects that represent operations:
struct Operation {
virtual ~Operation() {}
virtual bool operator()(Object&) = 0;
};
template<class T>
struct GreaterThen : Operation {
typedef T Object::*Member;
Member member;
const T value;
CompareGT(Member member, const T& value) : member(member), value(value) {}
bool operator()(Object& obj) { return (obj.*member > value); }
};
template<class T>
struct SetTo : Operation {
typedef T Object::*member;
Member member;
const T value;
SetTo(Member member, const T& value) : member(member), value(value) {}
bool operator()(Object& obj) { obj.*member = value; return true; }
};
Now we can build operation lists:
typedef std::vector<Operation*> OpList;
OpList operation;
operations.push_back(new GreaterThen<int>(&Object::Frame, 64));
operations.push_back(new SetTo<int>(&Object::State, 1));
We can use helper functions to avoid having to specify the template types:
template<class T>
Operation* opGreaterThen(T Object::*mem, const T& val) {
return new GreaterThen<T>(mem, val);
}
Assuming a similar helper for SetTo and using Boost.Assign the above becomes:
OpList operations = boost::assign::list_of
(opGreaterThen(&Object::Frame, 64))
(opSetTo (&Object::State, 1));
Executing the operations becomes the following then:
OpList::iterator it = operation.begin();
for( ; it != operations.end(); ++it) {
Operation& op = *it; // just for readability
if(!op(someObject)) break; // stop if operation returns false
}
Wow.
Reading through that slowly suggests what you're trying to end up with is an array of function calls and you can choose a different function with the same parameters (but different implementation) for different actions and choose the correct one for the correct case.
If that is the case, you're looking for function pointers. Try this tutorial.
You should be able to use a function pointer with an argument set and point it to the correct function based on your needs. You won't need an array of function pointers for this either - any function that matches the definition should do. From the tutorial, declare a function pointer like this:
int (TMyClass::*functptr)(classname, int, int) = NULL; // C++
Then assign it later:
this.functptr = &TMyClass::doitthisway;
While it is possible (although a pain) to have an array of arbitrary types, you pretty much never need it, since you have to know something about what is where to do anything interesting with it: for example, your 'TL;DR' example seems to look something like:
struct AIRule {
// Can only handle comparing ints, see later for more general solution.
typedef bool compare_type(AIObject*, AIObject::*int, int);
compare_type* compare;
AIObject* object;
AIObject::int* member;
int comparand;
};
So now you can do something like:
bool ai_equal(AIObject* object, AIObject::int* member, int comparand) {
return object->*member == comparand;
}
...
ai[n].compare = &ai_equal;
ai[n].object = some_object;
ai[n].member = &AIObject::some_member;
ai[n].comparand = 50;
...
if (ai[n].compare(ai[n].object, ai[n].member, ai[n].comparand)) {
...
}
This just moves the any type problem from the rules array to member though. C++ needs to know at least how many bytes a member is, and a string (for example) can be much bigger than an int. You can get around this by using pointers: which essentially is C++'s version of any, but you then need to delete it yourself (or you will leak memory!), at which point the interface method below becomes simpler.
If I was doing what you seem to want, I would use inheritance:
struct Sprite {
int frame;
double rotation;
Sprite() {
frame = 0;
rotation = 0.0;
}
virtual ~Sprite() {}
virtual void think() {
++frame;
}
virtual void draw() {
...
}
};
struct RotatingSprite : public Sprite {
int state;
MyShape() {
state = 0;
}
void think() {
Sprite::think();
if (state == 0 && frame > 64) {
state = 1;
rotation += 180.0;
}
}
};
Or a function pointer:
struct Sprite {
int frame;
double rotation;
void (*think)(Sprite*);
Sprite() {
frame = 0;
rotation = 0.0;
}
};
void rotate_think(Sprite* sprite) {
if (sprite->state == 0 && sprite->frame > 64) {
sprite->state = 1;
sprite->rotation += 180.0;
}
}
...
sprite->think = &rotate_think;
If you really need to do it dynamically I would recommend using the ++ part of C++. For the predicates (a predicate is just something that returns a boolean, like isLowerCase()) create an AIPredicate interface, and the actions an AIAction interface:
struct AIPredicate {
// "When you delete an AIPredicate, delete the full type, not just this interface."
virtual ~AIPredicate() {}
// "You can treat this as a function (operator()) but I'm not providing an implementation here ( = 0)"
virtual bool operator()(AIObject* object) = 0;
};
struct AIAction {
virtual ~AIAction() {}
virtual void operator()(AIObject* object) = 0;
};
struct AIRule {
// std::auto_ptr (or std::unique_ptr if you can use C++0x) will delete predicate for you.
// Add "#include <memory>" to your includes if it complains (most std headers will include it already)
std::auto_ptr<AIPredicate> predicate;
std::auto_ptr<AIAction> action;
};
Now you can make types like:
struct AIFrame : public AIPredicate {
// Implement the operator() member AICondition promises.
bool operator()(AIObject* object) {
return object->foo < 100;
}
};
...
// Use .reset() instead of = if you use std::unique_ptr.
ai[n].predicate = new AIFooIsLow();
If you want to have a very general predicate type, you can use the very powerful (and complicated) templates feature:
// The naming convention I'm using here is 'T'TitleCase for template parameters, TitleCase for types,
// lower_case for arguments and variables and '_'lower_case for members.
template<typename TMemberType, AIObject::TMemberType* TMember>
struct AIMemberEquals : public AIPredicate {
// Constructor: Initializes a new instance after it is created.
AIMemberEquals(TMemberType comparand) {
// Save comparand argument so we can use it in operator().
_comparand = comparand;
}
bool operator()(AIObject* object) {
return object->*TMember == comparand;
}
// Stores the value to compare.
TMemberType _comparand;
};
Unfortunately, creating templates looks a bit crazy:
ai[n].predicate = new AIMemberEquals<int, &AIObject::some_member>(100);
Read it as "create a new instance of (the type that AIMemberEquals applied to int and (the some_member member of AIObject) creates), with the argument 100".
When you have multiple predicates memory management becomes a bit more difficult without C++0x's unique_ptr or shared_ptr, types that will delete the object for you, since std::auto_ptr doesn't work in containers:
#include <vector>
struct AIData {
// vector is fairly close to AS3's Array type, it is a good default for
// arrays of changing or unknown size.
std::vector<AIPredicate*> predicates;
// Destructor: will be run before the memory for this object is freed.
~AIData() {
for (int i = 0; i != predicates.size(); ++i) {
delete predicates[i];
}
}
};
...
ai[n].predicates.push_back(new AIFooIsLow());
...
for (int i = 0; i != ai[n].predicates.size(); ++i) {
(*ai[n].predicates[i])(ai[n].object);
}
In C++0x:
struct AIData {
// unique_ptr will delete it for you, so no ~AIData() needed.
std::vector<unique_ptr<AIPredicate>> predicates;
};
Your final example could in C++ look something like:
std::auto_ptr<Shape> shape(new Shape());
...
std::auto_ptr<AIRule> rule(new AIRule());
rule->predicates.push(new AIMemberEquals<int, &Shape::state>(0));
rule->predicates.push(new AIMemberGreater<int, &Shape::frame>(64));
rule->actions.push(new AIAddMember<double, &Shape::rotation>(180.0));
rule->actions.push(new AISetMember<int, &Shape::state>(1));
shape->ai.push(rule); // .push(std::move(rule)); if you are using unique_ptr
Certainly not as pretty, but it works and is fairly flexible.

Lua, C++, and poor man's subclassing

I'm lead dev for Bitfighter, and we're working with a mix of Lua and C++, using Lunar (a variant of Luna, available here) to bind them together.
I know this environment does not have good support for object orientation and inheritance, but I'd like to find some way to at least partially work around these limitations.
Here's what I have:
C++ Class Structure
GameItem
|---- Rock
|---- Stone
|---- RockyStone
Robot
Robot implements a method called getFiringSolution(GameItem item) that looks at the position and speed of item, and returns the angle at which the robot would need to fire to hit item.
-- This is in Lua
angle = robot:getFiringSolution(rock)
if(angle != nil) then
robot:fire(angle)
end
So my problem is that I want to pass rocks, stones, or rockyStones to the getFiringSolution method, and I'm not sure how to do it.
This works for Rocks only:
// C++ code
S32 Robot::getFiringSolution(lua_State *L)
{
Rock *target = Lunar<Rock>::check(L, 1);
return returnFloat(L, getFireAngle(target)); // returnFloat() is my func
}
Ideally, what I want to do is something like this:
// This is C++, doesn't work
S32 Robot::getFiringSolution(lua_State *L)
{
GameItem *target = Lunar<GameItem>::check(L, 1);
return returnFloat(L, getFireAngle(target));
}
This potential solution does not work because Lunar's check function wants the object on the stack to have a className that matches that defined for GameItem. (For each object type you register with Lunar, you provide a name in the form of a string which Lunar uses to ensure that objects are of the correct type.)
I would settle for something like this, where I have to check every possible subclass:
// Also C++, also doesn't work
S32 Robot::getFiringSolution(lua_State *L)
{
GameItem *target = Lunar<Rock>::check(L, 1);
if(!target)
target = Lunar<Stone>::check(L, 1);
if(!target)
target = Lunar<RockyStone>::check(L, 1);
return returnFloat(L, getFireAngle(target));
}
The problem with this solution is that the check function generates an error if the item on the stack is not of the correct type, and, I believe, removes the object of interest from the stack so I only have one attempt to grab it.
I'm thinking I need to get a pointer to the Rock/Stone/RockyStone object from the stack, figure out what type it is, then cast it to the correct thing before working with it.
The key bit of Lunar which does the type checking is this:
// from Lunar.h
// get userdata from Lua stack and return pointer to T object
static T *check(lua_State *L, int narg) {
userdataType *ud =
static_cast<userdataType*>(luaL_checkudata(L, narg, T::className));
if(!ud) luaL_typerror(L, narg, T::className);
return ud->pT; // pointer to T object
}
If I call it thusly:
GameItem *target = Lunar<Rock>::check(L, 1);
then the luaL_checkudata() checks to see if the item on the stack is a Rock. If so, everything is peachy, and it returns a pointer to my Rock object, which gets passed back to the getFiringSolution() method. If there is a non-Rock item on the stack, the cast returns null, and luaL_typerror() gets called, which sends the app off into lala land (where the error handling prints a diagnostic and terminates the robot with extreme prejudice).
Any ideas on how to move forward with this?
Many thanks!!
Best solution I've come up with... ugly, but works
Based on the suggestions below, I came up with this:
template <class T>
T *checkItem(lua_State *L)
{
luaL_getmetatable(L, T::className);
if(lua_rawequal(L, -1, -2)) // Lua object on stack is of class <T>
{
lua_pop(L, 2); // Remove both metatables
return Lunar<T>::check(L, 1); // Return our object
}
else // Object on stack is something else
{
lua_pop(L, 1); // Remove <T>'s metatable, leave the other in place
// for further comparison
return NULL;
}
}
Then, later...
S32 Robot::getFiringSolution(lua_State *L)
{
GameItem *target;
lua_getmetatable(L, 1); // Get metatable for first item on the stack
target = checkItem<Rock>(L);
if(!target)
target = checkItem<Stone>(L);
if(!target)
target = checkItem<RockyStone>(L);
if(!target) // Ultimately failed to figure out what this object is.
{
lua_pop(L, 1); // Clean up
luaL_typerror(L, 1, "GameItem"); // Raise an error
return returnNil(L); // Return nil, but I don't think this
// statement will ever get run
}
return returnFloat(L, getFireAngle(target));
}
There are probably further optimizations I can do with this... I'd really like to figure out how to collapse this into a loop because, in reality, I will have a lot more than three classes to deal with, and this process is a bit cumbersome.
Slight improvement on the above solution
C++:
GameItem *LuaObject::getItem(lua_State *L, S32 index, U32 type)
{
switch(type)
{
case RockType:
return Lunar<Rock>::check(L, index);
case StoneType:
return Lunar<Stone>::check(L, index);
case RockyStoneType:
return Lunar<RockyStone>::check(L, index);
default:
displayError();
}
}
Then, later...
S32 Robot::getFiringSolution(lua_State *L)
{
S32 type = getInteger(L, 1); // My fn to pop int from stack
GameItem *target = getItem(L, 2, type);
return returnFloat(L, getFireAngle(target)); // My fn to push float to stack
}
Lua helper function, included as a separate file to avoid user needing to add this manually to their code:
function getFiringSolution( item )
type = item:getClassID() -- Returns an integer id unique to each class
if( type == nil ) then
return nil
end
return bot:getFiringSolution( type, item )
end
User calls this way from Lua:
angle = getFiringSolution( item )
I think you're trying to do the method dispatch in the wrong place. (This problem is symptomatic of a difficulty with all of these "automated" ways of making Lua interact with C or C++: with each of them, there's some magic going on behind the scenes, and it's not always obvious how to make it work. I don't understand why more people don't just use Lua's C API.)
I had a look at the Lunar web pages, and it looks to me as if you need to create a methods table on type T and then call the Luna<T>::Register method. There's a simple example on the web. If I'm reading the code correctly, none of the glue code in your question is actually the recommended way of doing things with Lunar. (I'm also assuming that you can implement these methods entirely as C++ calls.)
This is all pretty dodgy because the documentation on Lunar is thin.
A sensible alternative would be to do all the work yourself, and just associate each C++ type with a Lua table containing its methods. Then you have the Lua __index metamethod consult that table, and Bob's your uncle. Lunar is doing something close to these, but it's sufficiently dressed up with C++ templates that other goo that I'm not sure how to make it work.
The template stuff is very clever. You might want either to take the time to understand deeply how it works, or to reconsider if and how you want to use it.
Summary: for each class, make an explicit methods table, and register each class using the Lunar Register method. Or roll your own.
You should tell us what exactly does not work in your code. I suppose that it is Lunar<Rock>::check(L, 1) that fails for all non-Rocks. Am I correct?
Also it would be fine if you specified which version of Lunar you use (a link to it would be great).
If it is this one, then class type is stored in the Lua object metatable (one may say that this metatable is the type).
Looks like the simplest way to check if object is a Rock without patching Lunar is to call luaL_getmetatable(L, Rock::className) to get class metatable and to compare it with lua_getmetatable(L, 1) of your first argument (note luaL in the first function name). This is a bit hackish, but should work.
If you fine with patching Lunar, one of possible ways is to add some __lunarClassName field to the metatable and store T::name there. Provide lunar_typename() C++ function (outside of the Lunar template class -- as we do not need T there) then, and return from it the value of that __lunarClassName field of argument's metatable. (Do not forget to check if object has metatable and that metatable has such field.) You may check Lua object type by calling lunar_typename() then.
A bit of advice from personal experience: the more of business logic you push to Lua, the better. Unless you're pressed by severe performance constraints, you probably should consider to move all that hierarchy to Lua -- your life would become much simpler.
If I may help you further, please say so.
Update: The solution you've updated your post with, looks correct.
To do the metatable-based dispatch in C, you may use, for example, a map of integral lua_topointer() value of the luaL_getmetatable() for a type to a function object/pointer which knows how to deal with that type.
But, again, I suggest to move this part to Lua instead. For example: Export type-specific functions getFiringSolutionForRock(), getFiringSolutionForStone() and getFiringSolutionForRockyStone() from C++ to Lua. In Lua, store table of methods by metatable:
dispatch =
{
[Rock] = Robot.getFiringSolutionForRock;
[Stone] = Robot.getFiringSolutionForStone;
[RockyStone] = Robot.getFiringSolutionForRockyStone;
}
If I'm right, the next line should call the correct specialized method of robot object.
dispatch[getmetatable(rock)](robot, rock)
I suggest that you define an object oriented system in pure lua, and then write a custom binding to C++ for that aspect of the API.
Lua is well suited for prototype OO implementations, where tables are used for emulating classes, in which one entry has a function called new, which when called returns an appropriate table of the same 'type'.
From C++, however, make a LuaClass that has a .invoke method, accepting a C string (ie, a null-terminated const char array) to specify the name of the member function you want to call, and depending on how you want to handle variable arguments, have several templated versions of this .invoke method for zero, one, two, ... N arguments as neccessary, or define a method of passing a variable number of arguments into it, and there are many ways to do that.
For Lua, I suggest making two .invoke methods, one which expects an std::vector, and another that expects an std::map, but I'll leave that up to you. :)
In my last Lua/C++ project, I used only null-terminated arrays of C-strings, requiring lua to convert the string to an appropriate value.
Enjoy.
I was facing quite the same needs, and here is what I came up with.
(I had to do some minor changes to the Lunar header)
First, I've added a global "interface" for all the classes that will contains Lua methods.
I understand this could appear less flexible than the "original" way, but in my opinion it's clearer, and I do need it to perform dynamic casts.
class LuaInterface
{
public:
virtual const char* getClassName() const=0;
};
Yes, it only contains one pure virtual method, which will obviously return the static "className" attribute in the derived classes. That way, you can have polymorphism, with keeping this static name member needed by the templated lunar classes.
To make my life easier, I've also added some defines :
#define LuaClass(T) private: friend class Lunar<T>; static const char className[]; static Lunar<T>::RegType methods[]; public: const char* getClassName() const { return className; }
So you basically just have to declare a class like this :
class MyLuaClass: public LuaInterface
{
LuaClass(MyLuaClass)
public:
MyLuaMethod(lua_State* L);
};
Nothing particular here.
I also need a "singleton" (ouch, I know : it doesn't really have to be a singleton just do whatever you feel like to)
class LuaAdapter
{
//SINGLETON part : irrelevant
public:
const lua_State* getState() const { return _state; }
lua_State* getState() { return _state; }
template <class T>
void registerClass(const std::string &name)
{
Lunar<T>::Register(_state);
_registeredClasses.push_back(name);
}
void registerFunction(const std::string &name, lua_CFunction f)
{
lua_register(_state, name.c_str(), f);
_registeredFunctions.push_back(name);
}
bool loadScriptFromFile(const std::string &script);
bool loadScript(const std::string &script);
const StringList& getRegisteredClasses() const { return _registeredClasses; }
const StringList& getRegisteredFunctions() const { return _registeredFunctions; }
LuaInterface* getStackObject() const;
private:
lua_State* _state;
StringList _registeredClasses;
StringList _registeredFunctions;
};
For now, just look at the registerClass method : we store its name here in a StringList (just a list of string)
Now, the idea is to implement a proxy to register our classes :
template<class _Type>
class RegisterLuaClassProxy
{
public:
RegisterLuaClassProxy(const std::string &name)
{
LuaAdapter::instance()->registerClass<_Type>(name);
}
~RegisterLuaClassProxy()
{
}
};
We need to build one instance of each proxy for each LuaInterface class.
ie: in MyClass.cpp, after the standard "Lunar" method declaration :
RegisterLuaClass(MyClass)
With, again, a couple of defines :
#define RegisterLuaClassWithName(T, name) const char T::className[] = name; RegisterLuaClassProxy<T> T ## _Proxy(name);
#define RegisterLuaClass(T) RegisterLuaClassWithName(T, #T)
Do the same with the "functions" methods/proxy.
Now some little changes in the Lunar header :
remove the "userdataType" structure from the class, and define a single struct outside the class :
typedef struct { LuaInterface *pT; } userdataType;
(note that you will also need to add some static_cast inside the Lunar class)
Well, well. Now we have all the structures we need to perform our operation, I've defined it in the getStackObject() method of my LuaAdapter, based on your code.
LuaInterface* LuaAdapter::getStackObject() const
{
lua_getmetatable(_state, 1);
for(StringList::const_iterator it = _registeredClasses.begin(); it != _registeredClasses.end(); ++it)
{
// CHECK ITEM
luaL_getmetatable(_state, it->c_str());
if(lua_rawequal(_state, -1, -2)) // Lua object on stack is of class <T>
{
lua_pop(_state, 2); // Remove both metatables
userdataType *ud = static_cast<userdataType*>(luaL_checkudata(_state, 1, it->c_str()));
if(!ud) luaL_typerror(_state, 1, it->c_str());
return ud->pT;
}
else // Object on stack is something else
{
// Remove <T>'s metatable, leave the other in place for further comparison
lua_pop(_state, 1);
}
}
return NULL;
}
Here is the trick : since the returned pointer points to an abstract class, you can safely use dynamic_cast<> with it. And add some "intermediate" abstract classes, with nice virtual methods, like :
int fire(lua_State *L)
{
GameItem *item = dynamic_cast<GameItem*>(LuaAdapter::instance()->getStackObject());
if( item!= NULL)
{
item->fire();
}
return 0;
}
... I Hope this will help. Don't hesitate to correct me / add stuff / feedback.
Cheers :)