Jump to content
  • Advertisement
Sign in to follow this  

Perl style scalar type in C++?

This topic is 4822 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

in my game, various components need to signal each other by using a signal method
   void Signal(const string &id , Signal sig);

now the signal should be able to hold various different data types, in a stack (or a hash, would be equally as good).
    int
    int
    char
    string
I've only come up with 2 solutions. 1 is using ints and casting everything to ints (anything larger, is cast as a pointer - which is deleted afterwards !), or allocating memory using new and sizeof (again pointers, and void data type). What are you thoughts/suggestions/warnings? [Edited by - Genjix on March 6, 2005 5:37:16 PM]

Share this post


Link to post
Share on other sites
Advertisement
Why not just have different types of signals subclass Signal? better yet, why not have different per-signal methods? Best of all, why not use a premade signal/slot framework such as that provided by Boost?

Share this post


Link to post
Share on other sites
I won't go into the specific details, but having different subclasses for each signal wouldn't be appropriate.

Signal sig;
sig.Int(10);
sig.Str("Hello");
sig.Ptr((void*)&obj);

What would you do when a certain function needs to parse the structure?

void A::Foo(Signal s)
{
//... if i want to interpret
// values in s, how do i this?
// I still, can only access members
// that Signal has.
}

Eventhough boost's libraries are good, its signal/slot implementation doesn't suit what I'm doing. I do appreciate your help though.

[Edited by - Genjix on March 3, 2005 3:20:20 PM]

Share this post


Link to post
Share on other sites
Off the top of my head something this simple should do the job. Ofcourse it won't work for types you don't want to copy & you'll have to grab the thing by reference in your function (& not call the function the same name as the class :P), but you should really write a copy constructor for it anyway to handle such things.
struct Signal(){
/**/ Signal(char &value)
value(&new char(value)),
type(type_char)
{}
/**/ Signal(int &value)
value(&new int(value)),
type(type_int)
{}
/**/ Signal(string &value)
value(&new string(value)),
type(type_string)
{}
/**/ ~Signal(){delete value;}

void* value;
enum{
type_int,
type_char,
type_string
}type;
};

Share this post


Link to post
Share on other sites
Quote:
Original post by Genjix
//... if i want to interpret
// values in s, how do i this?
// I still, can only access members
// that Signal has.
By using RTTI. Of course, this can be ugly (just as variant types like you want can be ugly), which is why a premade signal/slot library is useful.

In what way is the boost signal/slot library insufficient for your needs?

Share this post


Link to post
Share on other sites

#ifndef NODE_H
#define NODE_H

#include "signal.h"

class World;

/**Base abstract 'Node' framework class

This class is the class inherited by each node.
Node's are different part's of the application,
and can be thought of as little clients.
Signals are recieved and sent as strings.*/

class Node
{
public:
/**update class pointer to parent*/
Node(World *par);
/***/
~Node();

/**Recieve and Interpret a signal

RecieveSignal should be overriden, by all derived
node classes*/

virtual void RecieveSignal(const string &id , Signal &sig);
protected:
/**Send a signal to parent to broadcast

Broadcast should not be overriden as it is used
to communicate with the other nodes, via the parent*/

void Broadcast(const string &id , Signal &sig);
/**Send a signal to parent to relay

SendSignal should not be overriden as it is used
to communicate with the other nodes, via the parent*/

void SendSignal(const string &name , const string &id , Signal &sig);
private:
World *parent; ///< Node's Parent
};

#endif



All the different nodes, are created, and registered with the app. Different nodes need to communicate, and parameters need to be passed around.

As for a new data type for each different type of signal... well the reciever and sender BOTH need to know the signal type (so reciever can cast back to type to read data), and since there are potentially lots of signals, and a broadcast...

ProPuke's solution is the simplest, and my favorite... but what happens with lots of data types, use pointers? I might as well cast everything to ints, and anything else read the pointer and cast as an int.

boost::any is exactly what i need (especially type checking)... but i need to link against boost, and its a bit OTT for whats needed. What would be better :D lmao, would be if anyone could tell me how its is able to accept any type, and how it internally stores the typeinfo.

If it helps, the system im (trying) to design is more like Qt's mechanism.

Thank you for your time.

Share this post


Link to post
Share on other sites
this is what I've decided to go for (I still want your ideas :) )

main.cpp


#include "world/world.h"
#include "node/testnode.h"
#include "event/eventinterpreter.h"

int main()
{
World myworld;

TestNode genericnode(&myworld);

myworld.Register("GenericNode",genericnode);

/*testing testing*/
Signal soh("this is message");
soh.params["age"] = 10;
soh.params["name"] = (int)"Amir Taaki";
myworld.Broadcast("hello",soh);
myworld.SendSignal("GenericNode","bye",soh);

/*tie our World to eventinterpreter*/
EventInterpreter ei(myworld,"amir.lua");

return 0;
}


signal.h

#ifndef SIGNAL_H
#define SIGNAL_H

#include "types/stlext.h"
#include <string>
using namespace std;

/**not yet implemented*/
class Signal
{
public:
/***/
Signal(const string &d);
/***/
~Signal();

map<string , int> params;///< signal parameters (cast to ints)
const string debug; ///< debug message
};

#endif


and I unroll the signal

cout << (const char*)sig.params["name"] << " is "
<< sig.params["age"] << "\n";

normally I wouldn't ever dream of doing something as simple as this :P

Share this post


Link to post
Share on other sites
You can store type info using polymorphism.

class BType
{
virtual ~BType() {}
};

template<typename T> class DType
{
public:
virtual ~DType() {}
T the_object;
/* appropriate constructors... */
};


In your 'any' class, you have a templated set function that creates an object of type DType<T>. You store this using a pointer to BType. Later, if you want to check to see if it's of type A, you attempt a dynamic_cast<DType<A>*>(ptr_to_BType). If it returns non-null, you've got a value object of DType<A> and can access the_object. If it returns null, it's not the right type.

I've got a non-boost variant class that operates this way. Let me slice it out of my lib and I'll pass it along. :D

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!