How do I load data to a templatized class

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • hall

    How do I load data to a templatized class


    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 - )

  • Kevin Saff

    #2
    Re: How do I load data to a templatized class

    "hall" <Xcrackhead_eX@ yahoo.se> wrote in message
    news:3F9E7761.5 050408@yahoo.se ...[color=blue]
    > 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.[/color]

    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 NotCopyConstruc tible {
    private: NotCopyConstruc tible (NotCopyConstru ctible 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.


    Comment

    • hall

      #3
      Re: How do I load data to a templatized class



      On 10/28/2003 7:11 PM Kevin Saff spoke thusly
      [color=blue]
      > "hall" <Xcrackhead_eX@ yahoo.se> wrote in message
      > news:3F9E7761.5 050408@yahoo.se ...
      >[color=green]
      >>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.[/color]
      >
      >
      > 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 NotCopyConstruc tible {
      > private: NotCopyConstruc tible (NotCopyConstru ctible const&) {}
      > };
      >
      > that is not copy constructible does not prevent vectors from being used for
      > classes that do indeed meet the requirement.
      >[/color]

      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) ?
      [color=blue]
      > 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.
      >
      >[/color]

      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::operato r>>(CartesVecto r & 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::strin g fName); // opens file fName for reading
      bool close(); // closes current file.

      // Operator >>
      InFile& operator>>(int& ); // integers
      InFile& operator>>(shor t int&);
      InFile& operator>>(Cart esVector &); // 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(st d::string fName){ // open(string n)
      bool ret = initInFile(fNam e); 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::initInF ile(string &fName){
      iF.open(fName.c _str(), ios::binary);
      return true;
      };

      // Operator >>

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

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

      InFile& InFile::operato r>>(CartesVecto r & 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 - )

      Comment

      • Kevin Saff

        #4
        Re: How do I load data to a templatized class

        "hall" <Xcrackhead_eX@ yahoo.se> wrote in message
        news:3F9F96D4.6 090309@yahoo.se ...[color=blue]
        > 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) ?[/color]

        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
        [color=blue]
        > 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::operato r>>(CartesVecto r & cv)
        > as a member of InFile. How would a template for operator>> look like in
        > this case?[/color]

        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::operato r>>(T& item)
        {
        iF.read (reinterpret_ca st <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


        Comment

        Working...