Archived

This topic is now archived and is closed to further replies.

Wyrframe

Templated function hassles

Recommended Posts

  
template <class T> int DoProgram (int argc, char* argv[]) { ... }
  
I use a templated class in this function. When compiling, it tells me that the above declaration line is "terminated incorrectly". Any chance you can tell me why? The reason I need to do this is because the compiler won't let me template the main() function. Somewhat understandable. [edit: added source tags] Edited by - Magmai Kai Holmlor on February 18, 2002 9:16:45 PM

Share this post


Link to post
Share on other sites
I think your code example has been munged by the php thingy.

trying putting it in square brackets with source and /source

I notice that your function does not parameterize on anything - so why do you need it to be a template?

Unless you instantiate something inside DoProgram based upon a template parameter.



Edited by - SteveC on February 18, 2002 2:53:50 PM

Share this post


Link to post
Share on other sites
His code looks like this:
    
template <class T> int DoProgram (int argc, char* argv[]) { ... }

If you're using MSVC I think you're forced to use (in this case) T as the return value or one of the parameters. If you're not using MSVC I'm not sure what the problem is.



Edited by - Null and Void on February 18, 2002 2:57:48 PM

Share this post


Link to post
Share on other sites

I''m using Borland''s BCC32 compiler (v5.5). I''ve been messing around with this, and still can''t get it to work quite right...

Continued efforts to help are highly appreciated!

Share this post


Link to post
Share on other sites
when you use templates, you can think of them as a large pool of functions. when you call such a function, the compiler cooses the right one for the args/return values you passed.. but when you don''t use the template class for args/return, the compiler does not know wich func it should coose...result: ERROR. This ist not a bad thing, as using templates makes no sense when you don''t pass a a templated arg/retval..

Share this post


Link to post
Share on other sites
  
#define STAMP template <class T>

int main(int argc, char* argv[]);
STAMP int DoProgram (int argc, char* argv[]); ;

int main(int argc, char* argv[]) {
return DoProgram(argc, argv);
}

STAMP int DoProgram (int argc, char* argv[]) {
// I need to make this a templated function in

// order to use the templated class below...


// My class...

ZArray *ca; char itype[16];

// Put either "int", "char", or "float" in itype[], and create the var based on that.


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

// I then give that class some commands, and it works based on it's own data type.


}


So, what you're saying, is that I should change this to...

  
STAMP T DoProgram (int argc, char* argv[]); ;
/* ============= */
int main(int argc, char* argv[]) {
return DoProgram<int>(argc, argv);
}


... right?



Edited by - wyrframe on February 18, 2002 3:47:29 PM

Share this post


Link to post
Share on other sites
why do you think a function must be templated in order to use template classes?
  
int DoProgram (int argc, char* argv[])
{
ZArray *ca;
char itype[16]; // why do you use an array here?

// put a value in itype

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

that will work fine

Share this post


Link to post
Share on other sites
quote:
Original post by Wyrframe
So, what you''re saying, is that I should change this to...


STAMP T DoProgram (int argc, char* argv[]); ;
/* ============= */
int main(int argc, char* argv[]) {
return DoProgram(argc, argv);
}



Since main must return int, this is all a bit pointless. What is it you''re trying to achieve with templates?



--
The Dilbert Principle: People are idiots.

Share this post


Link to post
Share on other sites
If I make these changes...


      
int DoProgram (int argc, char* argv[]);

int DoProgram (int argc, char* argv[]) {
// ...

}


... when the compiler gets to here...


ZArray *ca; // This is line 100
char itype[16]; // An array of chars, aka a string.


I get these compiler errors...


Error E2102 .\..\pex2.c 100: Cannot use template 'ZArray' without specifying specialization parameters in function DoProgram(int,char * *)
Error E2040 .\..\pex2.c 100: Declaration terminated incorrectly in function DoProgram(int,char * *)
[/source]

123cs, your code will not work. It gives the exact same errors.



Edited by - wyrframe on February 18, 2002 6:22:56 PM

[edit: munged source tags screwed up the view of the page]

Edited by - Magmai Kai Holmlor on February 18, 2002 9:18:09 PM

Share this post


Link to post
Share on other sites
Where''s the definition of ZArray? It looks like you need to instantiate it as a template.

--
The Dilbert Principle: People are idiots.

Share this post


Link to post
Share on other sites

  
#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.

Share this post


Link to post
Share on other sites
Your declaration "ZArray *ca;" is wrong. It needs to be "ZArray<type> *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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Guest 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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites