By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,361 Members | 3,185 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,361 IT Pros & Developers. It's quick & easy.

How do I load data to a templatized class

P: n/a

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

--
( - Remove capital X from email to reply - )

Jul 19 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
"hall" <Xc***********@yahoo.se> wrote in message
news:3F**************@yahoo.se...
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.
Jul 19 '05 #2

P: n/a


On 10/28/2003 7:11 PM Kevin Saff spoke thusly
"hall" <Xc***********@yahoo.se> wrote in message
news:3F**************@yahoo.se...
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.


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::operator>>(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::open(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::operator>>(int &i){
iF.read((char*)&i , sizeof(int));
return *this;
};

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

InFile& InFile::operator>>(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;
};

--
( - Remove capital X from email to reply - )

Jul 19 '05 #3

P: n/a
"hall" <Xc***********@yahoo.se> wrote in message
news:3F**************@yahoo.se...
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) ?
The compiler does the type checking for you, but each template is basically
compiled for each type parameter. So here,

Fii <short> bir; // is fine
Fii <string> biz; // compiler error
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::operator>>(CartesVector & cv)
as a member of InFile. How would a template for operator>> look like in
this case?


Actually, I had forgotten your requirement for both text-style and
binary-style io. Of course, it is the binary case that is trivial for cases
w/o pointers and references:

template <class T>
InFile& InFile::operator>>(T& item)
{
iF.read (reinterpret_cast <char*> (&item), sizeof (T));
return *this;
};

For text-based io, you can require your users to manually overload the standard stream extraction and insertion operators which is quite a reasonable requirement for this kind of thing. For your CartesVector class, this amounts to (something like):

class CartesVector{
float x,y,z;
friend std::istream& operator>> (std::istream&, CartesVector&);
friend std::ostream& operator<< (std::ostream&, CartesVector&);
public:
// ...
}

std::istream& operator>> (std::istream& is, CartesVector& cv)
{
return is >> cv.x >> cv.y >> cv.z;
}

std::ostream& operator<< (std::ostream&, CartesVector&)
{
return os << cv.x << cv.y << cv.z; //
may need to add spaces.
}

HTH.
Kevin
Jul 19 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.