Template question (C++ durr)

Started by
7 comments, last by vs322 15 years, 8 months ago
Ok so I finally started getting into mettaprograming and have come upon something that should be do-able, but I can't seem to get my compiler (or google) to really go along with what I'm trying to do. Can I set up a map / list / stl container of Template pointers, and then specify the class at insert time? ie: std::map<int,MyTmplate*> mpTmplate; mpTmpltate* = new MyTmplate<int>(); Or similar.... OR do I need to make a abstract base class with my template as a member and interface it that way? (with a different subclass for each type I might use with my template) ...seems to me that this is sort of redoing the work that templates would have allowed me to only do once.
Advertisement
The code example you gave is confusing, because it's quite incomplete and doesn't clearly demonstrate what you're trying to do.


Are you trying to make a 'template typedef', like:

typedef std::map<int, T*> TPtrMap;

TPtrMap<int> t; // where t is a map<int, int*>

?

If so, then no, you cannot do this until C++0x:
http://en.wikipedia.org/wiki/C%2B%2B0x#Template_typedefs
Unfortunately I'm not really certain what you're trying to do, but I do have a question:

What is the actual, practical, problem you're trying to solve? As opposed to the non-contextual problem you presented.

Edit:
Ah, RDragon1 might have hit on what you're trying to do. Real templated typedefs don't exist yet but there are two main workarounds:

- Stick the typedef in a templated struct:

template <class T>struct MyTemplate{    typedef std::map<int, T> type;};MyTemplate<int>::type   myIntMap;MyTemplate<float>::type myFloatMap;

- Use 'empty' inheritance:

template <class T>struct MyTemplate : std::map<int, T> { };MyTemplate<int>   myIntMap;MyTemplate<float> myFloatMap;
Sorry for my overly abstract example.

My actual template:

	template<class T> class LabelAndValue	{	public:		LabelAndValue(){}		LabelAndValue(std::string stLab){stLabel = stLab;}		std::string stLabel;		T tValue;		void GuiGramAdd(GuiMessenger::GuiGram ggIn);		std::string GetFormatedString();	};


I then want to have a map of my LabelAndValue Template where I don't know what the type of tValue will be before hand (either int, float or std::string atm). The map will be filled at load time from an XML file which specifies the stLabel and the type of the value. The value can change during run time through the GuiGramAdd function (which I have made versions of for int / float and std::string).

That is my specific reason for wanting to do this atm, but I am less interested in other ways to solve that specific problem as to whether this is something I can do with templates.

Edit: speedy replies tonight, no I'm not trying to do a template typedef as RDragon1 suggested.
you'll find that the compiler will claim that LabelAndValue<int> is a totaly different type from LabelAndValue<float>, of course the easy way around this is to simply have a base class which isn't templated, e.g. AbstractLabelAndValue, but then you lose most of the benefit of having the template class.

is this class purely for display purposes? if so, simple inheritence may be sufficient.

also, look into boost::any and similar containers. although, they are also prone to type-saftey issues.
"I am a donut! Ask not how many tris/batch, but rather how many batches/frame!" -- Matthias Wloka & Richard Huddy, (GDC, DirectX 9 Performance)

http://www.silvermace.com/ -- My personal website
Templates are resolved statically at compile time whereas reading from an XML file is a dynamic, run-time, operation. What I'm saying is that they're different beasts.

If your LabelAndValue can have a non-templated base class then you could store pointers to the base class and use it polymorphically, i.e.

template<class T>
class LabelAndValue : public LabelAndValueBase { /*...*/ }

std::map<int, LabelAndValueBase*> labels;

labels[5] = new LabelAndValue<int>;


But then you have to suffer with the non-templated base class.

Sometimes this a genuine problem, that is to say it's not a design flaw, and in those cases there is always boost::any and boost::variant.

I'd like to take a different approach to this issue though. Generally speaking the value stored in a label is maintained as text; it doesn't matter to the label whether that text happens to be interpreted as an integer or decimal later on. So you can probably do just fine by storing only a std::string as the value type and ditching the template idea.

For converting a string into a numeric type I'd recommend either boost::lexical_cast or std::stringstream.
Yeah that was sort of what I was thinking hand have already started on an abstract class that is simply an interface to this template.

Thanks for your time.
-vs

Edit to dmatter: The value and label are entirely different things, I am trying to make a data driven system (much more then necessary): I'm just trying to do a simple way of saving / and formatting things along the lines of "Name: Hiro Protagonist", "Age: 30" something along those lines.

And yeah I have been using std::ostringstream for some time (after finally breaking my bad sprintf habit);

2nd Edit to dmatter: after going back to my code I realized you were talking about the value weren't you? sry that I missed your point. Actually for this class I am working on it will work just fine if both label and value are stored as strings... man that simplifies things.

[Edited by - vs322 on August 11, 2008 9:55:19 PM]
Quote:Original post by vs322
Edit to dmatter: The value and label are entirely different things
To check we're on the same page: Presumably the value is the text that goes 'in' the label and each label has a name?

Quote:I am trying to make a data driven system (much more then necessary): I'm just trying to do a simple way of saving / and formatting things along the lines of "Name: Hiro Protagonist", "Age: 30" something along those lines.
My interpretation is that 'Name' and 'Age' are the names of two labels, and 'Hiro Protagonist' and '30' are the values of those labels respectively. A useful thing to note is that just because we as humans see '30' as an integer doesn't mean it has to stored as an int. It would simplify things for you to just say that the value of a label is text so store it all as a std::string.
Edit dueling for the lose. Again thanks for such a simple idea I hadn't thought of myself.

This topic is closed to new replies.

Advertisement