How do I load data to a templatized class

H

hall

I have a problem with my design of a templatized class. I'm trying to
figure out how to load and save the data inside it, but can't. My class
looks like this

------------------------------------
template <class tType> class Foo {

private:
tType data;

public:
load(InFile &in){
// Can't figure out what to write here
}
};
------------------------------------

my question is how to write the load function.

InFile is more or less a wrapper around an instream object that adds
some functionality missing in the basic classes. The most important
feature (in this context) is that binary and textfiles are treated
exactly the same by the user, eg load a float from an open file (inf is
the InFile object) is done by

float f;
inf >> f; // for text file
inf >> f; // for binary file

This makes file I/O very simple in my program where i need to read and
write to files in both binary and text format.

InFile has the operator >> overloaded for the basic types (integers,
floats, bool, char) as members of InFile, and for a few additional
classes. For these it would be nice to write the load function as

load(InFile & inf){ inf >> data; }

The problem is that the user of the class Foo could put any type of
object and as tType could be a type for which there is no overloading of
the >> operator, things would go wrong. In fact, i'm not sure that Foo
would compile as the compiler cannot know if tType is always a type for
which (inf >> tType) is allowed.

I'd appreachiate any kind of help or hints on how to solve this. If you
need more info in the InFile class, I can post a simple version of it.


regards
hall
 
K

Kevin Saff

hall said:
The problem is that the user of the class Foo could put any type of
object and as tType could be a type for which there is no overloading of
the >> operator, things would go wrong. In fact, i'm not sure that Foo
would compile as the compiler cannot know if tType is always a type for
which (inf >> tType) is allowed.

You are correct that it will fail if the user puts in a type which does not
have your overloaded operator>>. However, the compiler will not prevent you
from defining a template that makes this assumption. Consider std::vector,
for example. Vector only works for types that are copy constructible, since
it may need to copy its contents when the size increases. However, the fact
that users can define a class

class NotCopyConstructible {
private: NotCopyConstructible (NotCopyConstructible const&) {}
};

that is not copy constructible does not prevent vectors from being used for
classes that do indeed meet the requirement.

Probably a good solution to this problem would be to provide a template that
will make it easier for users to define operator>> for their classes, if
this is possible. In the general case where an object is "deep" this may be
quite difficult, but if the class has no pointers or references it is very
easy.

HTH,
Kevin.
 
H

hall

On 10/28/2003 7:11 PM Kevin Saff spoke thusly
You are correct that it will fail if the user puts in a type which does not
have your overloaded operator>>. However, the compiler will not prevent you
from defining a template that makes this assumption. Consider std::vector,
for example. Vector only works for types that are copy constructible, since
it may need to copy its contents when the size increases. However, the fact
that users can define a class

class NotCopyConstructible {
private: NotCopyConstructible (NotCopyConstructible const&) {}
};

that is not copy constructible does not prevent vectors from being used for
classes that do indeed meet the requirement.

So, when writing a template, the programer has to do the type checking
himself and not leave it to the compiler, as something like

template<tType> class Fii{
fun(tType T){
int f=T;
}
}

would compile (tType may be a int), but not run correctly if there is no
possability to cast tType to a int (if I understood you correctly) ?
Probably a good solution to this problem would be to provide a template that
will make it easier for users to define operator>> for their classes, if
this is possible. In the general case where an object is "deep" this may be
quite difficult, but if the class has no pointers or references it is very
easy.

HTH,
Kevin.

I'd appreachiate an example of how to do this (a quick sketch would be
perfect). In case it would make it easier, I send along a piece of my
code (a simplified version). Here, I have the class CartesVector that
currently works with InFile with InFile::eek:perator>>(CartesVector & cv)
as a member of InFile. How would a template for operator>> look like in
this case?

regards
hall



// code:

// -------------- class InFile ---------------------------------
class InFile{
std::ifstream iF; ///< wrapped ifstream object

bool initInFile(std::string &); // opens a file

public:

// Constructor / Destructor
InFile(){}; // Default constructor,
~InFile();

bool open(std::string fName); // opens file fName for reading
bool close(); // closes current file.

// Operator >>
InFile& operator>>(int&); // integers
InFile& operator>>(short int&);
InFile& operator>>(CartesVector &); // homegrown class

};

// -------------- class CartesVector------------------------------
class CartesVector{
float x,y,z;
public:
void set(float ix,float iy,float iz){
x=ix; y=iy; z=iz;
}
}



// IMPLEMENTATIONS
-----------------------------------------------------------------------------

InFile::~InFile(){ // DESTRUCTOR
iF.close();
};

bool InFile::eek:pen(std::string fName){ // open(string n)
bool ret = initInFile(fName); return ret;
}

bool InFile::close(){ // close
iF.close(); return true;
}


// Opens file and initiates object for read
// There is a lot more to this function, but the important part is this:
bool InFile::initInFile(string &fName){
iF.open(fName.c_str(), ios::binary);
return true;
};

// Operator >>

InFile& InFile::eek:perator>>(int &i){
iF.read((char*)&i , sizeof(int));
return *this;
};

InFile& InFile::eek:perator>>(short int &i){
iF.read((char*)&i , sizeof(short int));
return *this;
};

InFile& InFile::eek:perator>>(CartesVector & cv){ // operator>> for
float x,y,z; // CartesVector
iF.read((char*)&x, sizeof(float)); ok=iF;
iF.read((char*)&y, sizeof(float)); ok=(iF&&ok);
iF.read((char*)&z, sizeof(float)); ok=(iF&&ok);
cv.set(x,y,z);
return *this;
};
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top