Templated function hassles

Started by
15 comments, last by Wyrframe 22 years, 2 months ago

  #define STAMP template <class T>STAMP class ZArray {private:   T* data;   uint items;public:   STAMP ZArray(uint count) {      data = new T[count]; items = count;    };   ~ZArray() {     delete data; items = 0;   }   void setindex(uint idx, T  val);   void getindex(uint idx, T& val);   int readdata(ifstream& fdat, char& mode);   int showdata(ifstream& fidx);};  


That''s my class, in short. Externally-written functions ommited for shortness.

RIP GameDev.net: launched 2 unusably-broken forum engines in as many years, and now has ceased operating as a forum at all, happy to remain naught but an advertising platform with an attached social media presense, headed by a staff who by their own admission have no idea what their userbase wants or expects.Here's to the good times; shame they exist in the past.
Advertisement
Your declaration "ZArray *ca;" is wrong. It needs to be "ZArray&lttype> *ca;", where type should be some type to instantiate it with. Also, why are you using that awful macro STAMP? It's confusing the issue. In particular you shouldn't have STAMP in the constructor:

      STAMP // get rid of this!ZArray(uint count) {        data = new T[count]; items = count;    };  



Are you saying that you want to specify the type to provide to ZArray via DoProgram()? If so, do it like this:


  template<typename T>int DoProgram (int argc, char* argv[]) {  //...  ZArray<T> *ca;  //...}  


--
The Dilbert Principle: People are idiots.

Edit: ensure < and > show correctly.

Edited by - SabreMan on February 19, 2002 6:47:23 AM

But I need to be able to assign a different type to it at run-time...

     ZArray *ca;   if ( *itype == ''i'' ) ca = new ZArray<int>;   if ( *itype == ''c'' ) ca = new ZArray<char>;   if ( *itype == ''f'' ) ca = new ZArray<float>;  


I''m not making the ZArray of type ''T'', I''m making it an int, char, or float, depending on some input.
RIP GameDev.net: launched 2 unusably-broken forum engines in as many years, and now has ceased operating as a forum at all, happy to remain naught but an advertising platform with an attached social media presense, headed by a staff who by their own admission have no idea what their userbase wants or expects.Here's to the good times; shame they exist in the past.
Too bad you can''t do that.
If you want to use different types at run time you''ll have to either:
1) Use void pointers(EVIL!!!!!!)
or
2) Create your own wrapper class heirarchy(ick)
class Object;
class Int: public Object;
etc

I suspect that you could redesign your program such that you don''t need either though.
quote:Original post by Wyrframe
I''m not making the ZArray of type ''T'', I''m making it an int, char, or float, depending on some input.


Then you have a fundamental misunderstanding of how templates work. They provide what is known as parametric polymorphism, which is despatched in C++ purely at compile time. That is, you cannot instantiate a templated type at run time. Each instantiation of a templated class is an entirely different entity to any other, unless you do something else to relate them. For example, if you have the templated class:

  template<typename T>class SomeClass{public:  T getValue() const;  void setValue( T value );private:  T value_;};  


Then, if you instantiate this template as:

  SomeClass<int> sc_i;SomeClass<double> sc_d;  


You have created two classes with no inter-relationship other than they were created from the same template. They cannot be used interchangeably as they stand. If you do something like:

  SomeClass *p_sc1, *p_sc2;p_sc1 = new SomeClass<int>;p_sc2 = new SomeClass<double>;  


That is illegal C++ code, since you have not instantiated the SomeClass pointer with a type. Visual C++ accepts and compiles this, but that doesn''t make it correct. It is gibberish.

If you really want to achieve runtime polymorphism between these types then, as sjelkjd mentions, the mechanism to do so is the same as with non-templated classes: i.e. derive from a common root. For example:

  class Base{//...};template<typename T>class SomeClass : public Base{public:  T getValue() const;  void setValue( T value );private:  T value_;};  


Now you can have your pointer-to-indeterminate-type that you are trying to achieve:

  Base *p_sc1, *p_sc2;p_sc1 = new SomeClass<int>;p_sc2 = new SomeClass<double>;// ...do stuff with the objects...delete p_sc1;delete p_sc2;  


Note that the two template instantiations here will be carried out *at compile time*, that is two class definitions will be created. The only thing that gets deferred until runtime is the creation of instances of those classes.

Whether this is a good design for what you are trying to do is open to debate. In fact, don''t take the example I''ve provided you with as something I''d necessarily endorse, as I can think of several potential issues. I''m just demonstrating the mechanisms you seem to be confused with.

--
1st law of programming: Any given program, when running, is obsolete.
I think that template functions have to have a parameter of type T so that it knows what function to make, unlike template objects in which you explicitly specify type T. That is why std::sort does not use the angle brackets and vector does.
quote:Original post by Anonymous Poster
I think that template functions have to have a parameter of type T so that it knows what function to make, unlike template objects in which you explicitly specify type T. That is why std::sort does not use the angle brackets and vector does.


That''s incorrect. If the compiler cannot determine the type of the template parameter automatically, then the programmer must specify the parameter. vector<> and sort<> are examples of this in practice.

--
1st law of programming: Any given program, when running, is obsolete.

This topic is closed to new replies.

Advertisement