RPGDXThe center of Indie-RPG gaming
Not logged in. [log in] [register]
 
 
Post new topic Reply to topic  
View previous topic - View next topic  
Author Message
XMark
Guitar playin' black mage


Joined: 30 May 2002
Posts: 870
Location: New Westminster, BC, Canada

PostPosted: Fri Nov 12, 2004 9:51 pm    Post subject: C++ templates in an array [quote]

Okay, here's the deal. I'm working on a scripting engine (outside of the ARC Legacy, basically a general-purpose incomplete scripting engine that I can easily plunk into whatever future game projects I have). I'm planning to have multiple data types for variables, and the way I have the variable class implemented so far is with a template to determine the data type of class.value, so I could instantiate it like:

Code:

Variable <int>var1;
Variable <float>var2;


etc.

The problem I'm running into is I want to put them into a vector or an array, with mulitiple types of the template possible, like var[1] is an integer variable, var[2] is a float, et cetera.

Is this possible with templates or should I just use polymorphism instead?
_________________
Mark Hall
Abstract Productions
I PLAYS THE MUSIC THAT MAKES THE PEOPLES FALL DOWN!
Back to top  
Aptyp
Egg-Sucking Troll Humper


Joined: 09 Jun 2004
Posts: 36

PostPosted: Fri Nov 12, 2004 11:09 pm    Post subject: [quote]

What's the "vector or an array" interface that you plan to use to determine whether var[x] is a float or an int?
_________________
"Megaton" CRPG:
http://www.livejournal.com/users/megaton_game/
Back to top  
LeoDraco
Demon Hunter


Joined: 24 Jun 2003
Posts: 584
Location: Riverside, South Cali

PostPosted: Fri Nov 12, 2004 11:13 pm    Post subject: [quote]

A template in c++, when instantiated with a particular type, replaces the template type (call it "T") with that type. Essentially, what you get is code duplication on a massive scale. (Compare to parametric polymorphism in ML, where the same base code is reused, rather than duplicated.) Essentially, what you are suggesting would only work if all types (of the scripting language) inherit, polymorphically, from a common base class. (This, essentially, is your latter suggestion.) From the various compilers/interpreters that I have written, it is usually better to do this anyway: at the very least, you have a wrapper around the native type that is uniform across your language.

This can also allow for a single variable-class node in the parse tree, which, in and of itself, can be treated uniformly by visitors of the heirarchy.
_________________
"...LeoDraco is a pompus git..." -- Mandrake
Back to top  
tsb
I wanna be a ballerina!


Joined: 09 Oct 2004
Posts: 23

PostPosted: Sat Nov 13, 2004 12:32 am    Post subject: [quote]

Quote:
A template in c++, when instantiated with a particular type, replaces the template type (call it "T") with that type. Essentially, what you get is code duplication on a massive scale. (Compare to parametric polymorphism in ML, where the same base code is reused, rather than duplicated.)
Template classes are only recompiled once per template argument set, so it's hardly "massive" code duplication. (more importantly, the code that is duplicated is done purely by the compiler. This is still much preferable to having humans do the replicating)

The easiest way to effect variants in C++ is to simply use boost::any.
_________________
—andy
http://ika.sf.net
Back to top  
biggerUniverse
Mage


Joined: 18 Nov 2003
Posts: 326
Location: A small, b/g planet in the unfashionable arm of the galaxy

PostPosted: Sat Nov 13, 2004 1:12 am    Post subject: [quote]

"Use polymorphism." is the quick answer, but perhaps it would help if you could tell us what you plan to use it for.
_________________
We are on the outer reaches of someone else's universe.
Back to top  
LeoDraco
Demon Hunter


Joined: 24 Jun 2003
Posts: 584
Location: Riverside, South Cali

PostPosted: Sat Nov 13, 2004 2:45 am    Post subject: [quote]

tsb wrote:
Quote:
A template in c++, when instantiated with a particular type, replaces the template type (call it "T") with that type. Essentially, what you get is code duplication on a massive scale. (Compare to parametric polymorphism in ML, where the same base code is reused, rather than duplicated.)
Template classes are only recompiled once per template argument set, so it's hardly "massive" code duplication. (more importantly, the code that is duplicated is done purely by the compiler. This is still much preferable to having humans do the replicating)

The easiest way to effect variants in C++ is to simply use boost::any.


The point was not so much the size of the duplication, but that duplication occured at all. With what he has, he couldn't do:

Code:
Variable<int> ar[10];
ar[0] = Variable<float>(42.0);
ar[1] = Variable<int>(42);


which is, essentially, what I believe he was going for.
_________________
"...LeoDraco is a pompus git..." -- Mandrake
Back to top  
Mandrake
elementry school minded asshole


Joined: 28 May 2002
Posts: 1341
Location: GNARR!

PostPosted: Sat Nov 13, 2004 2:53 am    Post subject: [quote]

Polymorphism does work well for this. Just use pointers, and create a vector of pointers to the base class. This way, you have a base class variable. Then base class int, sting, etc all inherit from it and can be stored in a vector.
_________________
"Well, last time I flicked on a lighter, I'm pretty sure I didn't create a black hole."-
Xmark

http://pauljessup.com
Back to top  
tsb
I wanna be a ballerina!


Joined: 09 Oct 2004
Posts: 23

PostPosted: Sat Nov 13, 2004 5:00 am    Post subject: [quote]

LeoDraco wrote:
The point was not so much the size of the duplication, but that duplication occured at all. With what he has, he couldn't do:

Code:
Variable<int> ar[10];
ar[0] = Variable<float>(42.0);
ar[1] = Variable<int>(42);


which is, essentially, what I believe he was going for.

Right, but you can do something along these lines:
(untested, but should be enough to get the jist)
Code:

struct Variant {
    virtual ~Variant() {
    }
};

template <typename T>
struct VariantImpl : Variant {
    Variant(const T& t)
    : value(t) {
    }

    T value;
};

template <typename T>
Variant* box(const T& t) {
    return new VariantImpl<T>(t);
}

template <typename T>
T unbox(Variant* v, T* = 0) {
    VariantImpl<T>* impl = dynamic_cast<VariantImpl<T>*>(v);
    if (impl == 0) {
        throw std::exception("Could not unbox: types don't match");
    } else {
        return impl->value;
    }
}

std::vector<Variant*> ar;
ar.push_back(box(3.1415926));
ar.push_back(box("hello!"));

float f = unbox<float>(ar[0]);
char* c = unbox<char*>(ar[1]);

_________________
—andy
http://ika.sf.net
Back to top  
XMark
Guitar playin' black mage


Joined: 30 May 2002
Posts: 870
Location: New Westminster, BC, Canada

PostPosted: Sat Nov 13, 2004 8:30 am    Post subject: [quote]

yeeeeeek. hehe, I think I'm just going to do polymorphism then :)
_________________
Mark Hall
Abstract Productions
I PLAYS THE MUSIC THAT MAKES THE PEOPLES FALL DOWN!
Back to top  
Joakim
Tenshi's Bitch (Peach says "Suck it!")


Joined: 05 Apr 2004
Posts: 64

PostPosted: Sun Nov 28, 2004 12:21 am    Post subject: [quote]

I'm doing polymorphism in my own upcoming scripting language, and it works just great! Some things have caused me headackes like when I had to implement the table (eg. arrays with string keys aka dictionaries or lists) object and all that goes with that.

I am using simple reference counting to handle memory management for the objects, kinda like this:
Code:

class ScriptObject
{
private:
    int reference_count;
public:
    ScriptObject() { reference_count = 0;}
    void hook() { reference_count++; }
    void unhook() { if(reference_count < 2) delete this; else reference_count--; }
    virtual ~ScriptObject() = 0;
};

And then I only ever reference it from a special reference class, which only provides read only access to the actual object:
Code:

class ScriptObjectReference
{
private:
    ScriptObject * object;
public:
    ScriptObjectReference(const ScriptObjectReference &r) { object = r.object; object->hook(); }
    void operator = (const ScriptObjectReference &r) { object->unhook(); object = r.object; object->hook(); }
    ScriptObjectReference(ScriptObject * o) { object = o; object->hook(); }
    void operator = (ScriptObject * o) { object->unhook(); object = o; object->hook(); }
    const ScriptObject & obj() { return *object; }
    ~ScriptObjectReference() { object->unhook(); }
};

Then to create an object and use it, I do (assume ScriptObject_String is derived from ScriptObject):
Code:

ScriptObjectReference myref = new ScriptObject_String("Hello, World!");
std::cout << myref.obj().toString() << std::endl;
// Violá! When myref goes out of scope, the string object is automatically deleted.

There's a but more to it of course, but uhm yeah, don't know if this is useful to you or not... It's probably less useful if you're only dealing with simple types.
Back to top  
Bjorn
Demon Hunter


Joined: 29 May 2002
Posts: 1425
Location: Germany

PostPosted: Sun Nov 28, 2004 10:24 pm    Post subject: [quote]

Heh, that "script object" looks more like a smart pointer class, which makes a good template so that you'd be able to wrap it around instances of any type. :-)
Back to top  
Joakim
Tenshi's Bitch (Peach says "Suck it!")


Joined: 05 Apr 2004
Posts: 64

PostPosted: Sun Nov 28, 2004 10:42 pm    Post subject: [quote]

It is indeed part of a smart pointer system :)

However, it is also the base class from which all objects (like ScriptObject_Nil, ScriptObject_String, etc.) is derived. I guess we'll see how well it works out ;) (I'm currently finishing off my VM, although it will need tweaking later on when my compiler is in the working)
Back to top  
Post new topic Reply to topic Page 1 of 1 All times are GMT
 



Display posts from previous:   
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum