|
|
View previous topic - View next topic |
Author |
Message |
XMark Guitar playin' black mage
Joined: 30 May 2002 Posts: 870 Location: New Westminster, BC, Canada
|
Posted: 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
|
|
Back to top |
|
|
LeoDraco Demon Hunter
Joined: 24 Jun 2003 Posts: 584 Location: Riverside, South Cali
|
Posted: 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
|
Posted: 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
|
Posted: 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
|
Posted: 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!
|
Posted: 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
|
Posted: 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
|
Posted: 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
|
Posted: 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
|
Posted: 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
|
Posted: 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 |
|
|
|
Page 1 of 1 |
All times are GMT
|
|
|
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
|
|