Skip to main content
gamedev.net
🔒 Locked

Templates

Started by drago Oct 14, 2000 at 1:15 PM 12 replies 1.1k views
Original Post
drago
drago
Hello, Is it possible to have a template method within a "normal" class? e.g.
    
class CExample
{
     template <class T> T    GetVariable(const enum VARS& var);
     template <class T> void SetVariable(const enum VARS& var, T& tVariable);
};
[/source]

What I''m trying to do is, create a general Get* method for all member variables in a class. So the method has to be able to return both a [source]float[/source] as well as an [source]int    
. Currently, I''m using the void datatype to cast each datatype (float''s, int''s, struct''s, etc.) into the method. Or maybe I should just overload the method for each datatype? Any suggestions would be appreciated. ---------- Mail me, Drago's OpenGL Website
osu!
risingdragon3
risingdragon3
According to the ANSI C++ standard, yes.
According to MSVC, no.
According to Borland C++Builder, yes. (At least version 4+)
According to GNUC++, yes. (Tho'' latest version)
There you go. Depends on what compiler your using, and whether it is up to date w/ the standard.

------------------------------
BCB DX Library - RAD C++ Game development for BCB
Zipster
Zipster
quote:

Or maybe I should just overload the method for each datatype?


I don''t think the compiler classifies functions with different return values as overloaded. It will give you an error. Hell, it gave me one!
NuffSaid
NuffSaid
quote:
Original post by c++freak

According to the ANSI C++ standard, yes.
According to MSVC, no.
According to Borland C++Builder, yes. (At least version 4+)
According to GNUC++, yes. (Tho'' latest version)
There you go. Depends on what compiler your using, and whether it is up to date w/ the standard.

------------------------------
BCB DX Library - RAD C++ Game development for BCB



Does that mean that MSVC isn''t ANSI compliant?
==========================================In a team, you either lead, follow or GET OUT OF THE WAY.
Wilka
Wilka
quote:

Does that mean that MSVC isn''t ANSI compliant?



Yep, but no compiler is yet - MSVC is just worse than most of them.
drago
drago
Isn''t there an alternative to using the void datatype as a "pseudo" template? I don''t find all that type casting too nice.

what I''m doing now is this:
    // Class declaration

class S_CConfiguration
{
void* GetVariable(const enum CONFIG_VARS& var);
void SetVariable(const enum CONFIG_VARS& var);
};

void* S_CConfiguration::GetVariable(const enum CONFIG_VARS& var)
{
switch(var)
{
case RES_WINDOW:
{
return &m_cresWindow;
};
case GL_FOV:
{
return &m_fglFOV;
};
default: return NULL;
}
}

void S_CConfiguration::SetVariable(const enum CONFIG_VARS& var, void* pvNewVar)
{
switch(var)
{
case RES_WINDOW:
{
m_cresWindow = *(S_CResolution)pvNewVar;
} break;
case GL_FOV:
{
m_fglFOV = *(float)pvNewVar;
} break;
default: return;
}
}

// This is how I would use the class.

void ExampleFunction()
{
S_CConfiguration *pccConfig = new S_CConfiguration;

float fFov = 90.0f;
pccConfig->SetVariable(GL_FOV, &fFov);
if(*(float*)pccConfig->GetVariable(GL_FOV) == 90.0f)
{
PostQuitMessage(0);
}

delete pccConfig;
}


Now, how would you guys (or girls) do this?

----------
Mail me, Drago's OpenGL Website
osu!
Kylotan
Kylotan
quote:
Original post by drago

Hello,

Is it possible to have a template method within a "normal" class?
e.g.

class CExample
{
template T GetVariable(const enum VARS& var);
template void SetVariable(const enum VARS& var, T& tVariable);
};




Although one poster says it is supported by the standard, I don't see how it can be. Normally, the specific type(s) being used by an instance of a template class are picked at compile time, byt being explicitly stated, for example:

list<int> intList;

This is so the compiler can make a copy of the List class with ints in the place of the type parameter.

However, given the CExample class above, it has no way of doing that, since an instance of CExample doesn't contain any information on what type 'T' should be.

To C++ Freak who claims this is legal... how would you call the given functions? Like so:

CExample cex;
int result = cex.GetVariable<int>(/* some parameters */);

I've never seen such syntax in any textbook, so I'm intrigued...

Edited by - Kylotan on October 22, 2000 4:03:28 PM
null_pointer
null_pointer
Original poster:

I presume this is what you are trying to do?


class CExample
{
public:

typedef enum VARS { x, y, z };

template &lttypename T>
void SetVariable(enum VARS variable, T& data)
{
switch( variable )
{
case x:
m_x = data;
break;
case y:
m_y = data;
break;
case z:
m_z = data;
break;
}
}

template &lttypename T>
T& GetVariable(enum VARS variable)
{
switch( variable )
{
case x:
return( m_x );
break;
case y:
return( m_y );
break;
case z:
return( m_z );
break;
}
}

private:
int m_x;
char m_y;
float m_z;
};

int main(int, char*)
{
CExample test;

int my_x = 5;
char my_y = '6';
float my_z = 0.10f;

test.SetVariable(CExample::x, my_x);
test.SetVariable(CExample::y, my_y);
test.SetVariable(CExample::z, my_z);

return 0;
}



The GetVariable() function will not work, as other people have stated, since you cannot differentiate functions only by return type.

BTW, what are you using this for? To make writing accessor functions (set/get functions) easier? Just make the variables public. The only gripe about public variables is that they can be changed by any code, which is what your accessors end up doing anyway.


Kylotan:

This works fine as a console app in MSVC 6.0 SP4:


#include
#include
#include

using namespace std;

class file
{
public:
file(const string& name) : stream(name.c_str(), ios::in | ios::out | ios::binary) {}

void open(const string& name) { stream.close(); stream.open(name.c_str(), ios::in | ios::out | ios::binary); }
void close() { stream.close(); }

template &lttypename T>
void write(T& data) { stream.write((char*) &data, sizeof(data)); }

template &lttypename T>
void read(T& data) { stream.read((char*) &data, sizeof(data)); }

private:
fstream stream;
};

int main(int argc, char* argv[])
{
float f = 0.10f;
int x = 5;
char c = '6';

// open a file and write some values to it
file myfile1("example.txt");
myfile1.write(f);
myfile1.write(x);
myfile1.write(c);
myfile1.close();

// assign other values to test file-reading
f = 5.38f;
x = 432905;
c = '?';

// open the same files and read the values back into the objects
file myfile2("example.txt");
myfile2.read(f);
myfile2.read(x);
myfile2.read(c);
myfile2.close();

// output the changed values
cout << f << " " << x << " " << c << endl;

return 0;
}



saves typing...




- null_pointer
Sabre Multimedia


Edited by - null_pointer on October 22, 2000 6:49:05 PM
Atavist
Atavist
How sweet is that
Thanks null_pointer, I didn''t know that was possible in msvc6 (or anywhere else..)
But I believe this is quite a powerful new tool It''s going right into my game engine.

Just because the church was wrong doesn't mean Galileo wasn't a heritic.
It just means he was a heritic who was right.
Just because the church was wrong doesn't mean Galileo wasn't a heretic.It just means he was a heretic who was right.
drago
drago
null_pointer: yes I''m trying to make get/set functions easier. It was just an idea based on the commomn get/set functions and OpenGL''s glGetInteger()(?or whatever it''s name is).. and I''d rather not "public" the system variables (that''s what the example class really is meant to handle)..

----------
Mail me, Drago's OpenGL Website
osu!
risingdragon3
risingdragon3
Dolt! I should of checked this thread earlier!
Actually yes you can differentiate on return types, I did this for my random number functions:
    
template <class T> T Random() {
//whatever

}

//to call:

int Rand = Random<int>();
float Rand = Random<float>();

Also, using templates for read/write, I have done that too, I have to tell ya, saves a lot of typing!!!
(all those sizeof''s)


------------------------------
BCB DX Library - RAD C++ Game development for BCB
null_pointer
null_pointer
c++freak: Here's an excerpt from MSDN:

quote:

Restrictions on Overloaded Functions

Several restrictions govern an acceptable set of overloaded functions:

1. Any two functions in a set of overloaded functions must have different argument lists.

2. Overloading functions with argument lists of the same types, based on return type alone, is an error.



My C++ book confirms this. Why does MSVC 6.0 SP4 allow it?



- null_pointer
Sabre Multimedia


Edited by - null_pointer on October 22, 2000 10:19:17 PM
Void
Void
quote:
Original post by null_pointer
This works fine as a console app in MSVC 6.0 SP4:


#include
#include
#include

using namespace std;

class file
{
public:
file(const string& name) : stream(name.c_str(), ios::in | ios::out | ios::binary) {}

void open(const string& name) { stream.close(); stream.open(name.c_str(), ios::in | ios::out | ios::binary); }
void close() { stream.close(); }

template
void write(T& data) { stream.write((char*) &data, sizeof(data)); }

template
void read(T& data) { stream.read((char*) &data, sizeof(data)); }

private:
fstream stream;
};

int main(int argc, char* argv[])
{
float f = 0.10f;
int x = 5;
char c = ''6'';

// open a file and write some values to it
file myfile1("example.txt");
myfile1.write(f);
myfile1.write(x);
myfile1.write(c);
myfile1.close();

// assign other values to test file-reading
f = 5.38f;
x = 432905;
c = ''?'';

// open the same files and read the values back into the objects
file myfile2("example.txt");
myfile2.read(f);
myfile2.read(x);
myfile2.read(c);
myfile2.close();

// output the changed values
cout << f << " " << x << " " << c << endl;

return 0;
}




Null pointer: I believe there is a bug with that class. Opening a file with ios::in | ios::out requires the file (example.txt) to exists beforehand, or the stream constructor will fail..

    
#include <iostream>
#include <fstream>

using namespace std;

void main()
{
fstream fff("Doesnotexist.txt", ios::in | ios::out);

if (!fff)
cout << "Creation error" << endl;
}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.