CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    Jun 2009
    Posts
    5

    Talking Templated class and iostream overloading

    Well first I want to say hello to all the users here.
    I'm a beginner in C++ and I'm trying to program a vector class for a Math Utility library I'm working on as my first big project written in C++... Well everything is working as expected but I have some questions.
    -Info:
    All my vector class is in a header file and using the namespace mut (it stands for Math Utility Toolkit, I might change the name but it's ok for the moment) and I'm using a template like this:
    Code:
    namespace mut{
        template <class T=int> //Default vector storage is int
            class vector{
                  .......
            }
    }
    I wanted to add iostream operators to my class and this is what I did:
    Code:
    //IOSTREAM operators
    
        template <class T>
        ostream& operator<<(ostream& os, vector<T> &vec){
            int i = 0;
            os << "(";
            for(i = 0; i < vec.length() - 1; i++){
                os << vec[i] << ", ";
            }
            os << vec[i] << ")" << endl;
            return os;
        }
    
        template <class T>
        istream& operator>>(istream& is, vector<T> &vec){
            int i = 0;
            for(i = 0; i < vec.length(); i++){
                is >> vec[i];
            }
            return is;
        }
    So my question is:
    I used the template again since these operators are outside the class definition but I don't know if there is a better way or if this is ok...

    And a second question is "is there a better way of formatting the output for my vector like so?": (vec[0], vec[1], vec[2]...)
    I achieved this format but i don't know if the function can be optimised...
    Well thanks in advance!
    If you need more info, let me know
    BB!

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Templated class and iostream overloading

    Quote Originally Posted by beta3designs View Post
    I used the template again since these operators are outside the class definition
    Before you do anything else, please append the appropriate namespace onto "vector" in your code.
    Code:
    template <class T>
        ostream& operator<<(ostream& os,  mut::vector<T> &vec){
    The reason is that there already is a "vector" class in C++. Leaving the term "vector" without a namespace could cause compiler errors if your code is included in any source module that uses std::vector.

    As a matter of fact, all of those types should be prepended with their appropriate namespace (i.e. std::ostream, etc.). If you already have a "using namespace" clause before that code, get rid of it.

    Edit: Why are you not using the existing std::vector class? Why do you need to create your own?

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; June 25th, 2009 at 09:40 AM.

  3. #3
    Join Date
    Jun 2009
    Posts
    5

    Re: Templated class and iostream overloading

    Before you do anything else, please append the appropriate namespace onto "vector" in your code.
    Sorry, I forgot to say it was in namespace mut{} but outside class vector{}.
    Ok thanks ill get rid of using namespace std...
    And well it's just for the library... i like to program everything myself and since it is a math library i thought it would be good to have my own vector class...
    Thanks for your help!
    Still willing to know if there is a better way for what I did.
    Thanks in advance!
    BB!

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Templated class and iostream overloading

    Quote Originally Posted by beta3designs View Post
    i like to program everything myself and since it is a math library i thought it would be good to have my own vector class...
    So is the goal to have a math library, or to maintain a vector class?

    That is the question I always ask to someone who wants to write everything themselves. It's as if you're building a house, and instead of buying a hammer, you make your own hammer, instead of buying paint, you make your own paint, etc. While you're making your own hammer and making your own paint (and then have to test if your home made version works), another person is building the same house using store bought hammer and paint, and is almost finished by the time you've got your home-made hammer and paint solution finished.

    Unless there is a compelling reason to write things yourself, you should always consider the standard containers, even if just to quickly prototype your code to see if it actually will work.

    Still willing to know if there is a better way for what I did.
    Code:
    ostream& operator<<(ostream& os, vector<T> &vec){
    The second parameters should be a const reference. You are not changing values, you are merely reading from the vector. If you get a compiler error if you make it a const reference, it is more than likely going to be this:
    Code:
     os << vec[i] << ", ";
    Operator [] must have two versions, a const and non-const version. I don't know if you provided it, but I'm preparing you for what could cause a problem once you start passing const references to your vector class.

    Otherwise, there is really no difference if the template function is inline or not inlined. The only thing you have to be aware of is that the non-lined version of the template function has to still "ride" with the template header, i.e., the code must be included at the end of the template declaration.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; June 25th, 2009 at 10:08 AM.

  5. #5
    Join Date
    Apr 2004
    Location
    Canada
    Posts
    1,342

    Re: Templated class and iostream overloading

    Quote Originally Posted by Paul McKenzie View Post
    Edit: Why are you not using the existing std::vector class? Why do you need to create your own?
    It sounds like beta3designs is writing a class to represents a mathematical vector (as in vector quantity, as opposed to scalar quantity), and not the kind of "vector" that std::vector is.

    Now whether it makes sense to implement the mathematical vector class in terms of std::vector, is another question. (I'd argue yes, just be careful to avoid name clashes )
    Old Unix programmers never die, they just mv to /dev/null

  6. #6
    Join Date
    Jan 2004
    Location
    Düsseldorf, Germany
    Posts
    2,401

    Re: Templated class and iostream overloading

    Quote Originally Posted by beta3designs View Post
    Code:
        template <class T>
        ostream& operator<<(ostream& os, vector<T> &vec){
            int i = 0;
            os << "(";
            for(i = 0; i < vec.length() - 1; i++){
                os << vec[i] << ", ";
            }
            os << vec[i] << ")" << endl;
            return os;
        }
    What if the vector is empty (size 0)? Unless you are preventing zero-size vectors in some smart way, your operator should pay attention to that case.
    More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason - including blind stupidity. --W.A.Wulf

    Premature optimization is the root of all evil --Donald E. Knuth


    Please read Information on posting before posting, especially the info on using [code] tags.

  7. #7
    Join Date
    Jun 2009
    Posts
    5

    Re: Templated class and iostream overloading

    Ok thanks, I know sometimes I should use standard code, but I wanted to do it to learn too... I'm a newbie C++ programmer and I still have to learn a lot... so that's why I wanted to write it myself, so I could learn from my own mistakes.
    Operator [] must have two versions, a const and non-const version. I don't know if you provided it, but I'm preparing you for what could cause a problem once you start passing const references to your vector class.
    I have made those modifications and it works, but I don't really understand why I need a constant version can you explain it please?
    Otherwise, there is really no difference if the template function is inline or not inlined. The only thing you have to be aware of is that the non-lined version of the template function has to still "ride" with the template header, i.e., the code must be included at the end of the template declaration.
    So can I get those operators with the rest of my operators inline inside the class definition?? If so can you tell me how?
    Thanks for the help!!! It is really appreciated.

    EDIT:
    What if the vector is empty (size 0)? Unless you are preventing zero-size vectors in some smart way, your operator should pay attention to that case.
    Yes i have dealt with vector size = 0 but thanks for pointing out i should take that in to count...
    Thanks anyway for the help guys!
    And the vector I am writing I think is pretty similar to the one in std::vector in its base form... but I'm planning to add Mathematical operators and functions to it.
    Last edited by beta3designs; June 25th, 2009 at 02:01 PM.

  8. #8
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Templated class and iostream overloading

    Quote Originally Posted by beta3designs View Post
    I have made those modifications and it works, but I don't really understand why I need a constant version can you explain it please?
    When you pass a const reference to an object, any function you call on that object must be const. So if you're passing a const reference to a mut::vector, and within that function you're calling operator [] (which is a member function of mut::vector), it must be const.

    That is called const correctness in C++. When an entity is const, it is a contract that states that the entity will not be changed, else a compiler error will occur. You should study up as soon as possible on const correctness, as its one of the basics of writing proper C++ code. As a matter of fact, this should have been studied before writing one line of template code.
    So can I get those operators with the rest of my operators inline inside the class definition?
    What did you attempt? It's no different than writing other functions inline.
    And the vector I am writing I think is pretty similar to the one in std::vector in its base form...
    Given some of the errors you were making with the small bit of code, I think you better post your vector class because it is more than likely to have other issues that experienced C++ programmers would identify.

    Regards,

    Paul McKenzie

  9. #9
    Join Date
    Jun 2009
    Posts
    5

    Re: Templated class and iostream overloading

    Thanks for the explanation gonna check constant correctness right now... yeah I think it seems I forgot to learn some of the basics xD
    Given some of the errors you were making with the small bit of code, I think you better post your vector class because it is more than likely to have other issues that experienced C++ programmers would identify.
    Well that makes sense... anyway it works pretty well... but it may have some errors so I'll post it.
    What did you attempt? It's no different than writing other functions inline.
    Well don't know, first I tried to put it inline with the rest of my functions but it wasn't working some strange errors happened so I thought of taking it out, since it was an iostream operator and not a vector operator?
    well I post my class so you can help me better
    Code:
    /*
        MUT~ Math Utility Toolkit
        Written by Alejandro Valero (a.k.a. beta3designs)
        Copyright (c) 2009
        Contact: beta3designs@gmail.com
    
        This file is part of MUT.
    
        MUT is free software: you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.
    
        MUT is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.
    
        You should have received a copy of the GNU General Public License
        along with MUT.  If not, see <http://www.gnu.org/licenses/>.
    
    */
    /**
    */
    
    #ifndef MUT_VECTOR_H
    #define MUT_VECTOR_H
    
    #include <iostream>
    
    namespace mut{
        template <class T=int> //Default vector storage is int
        class vector{
            public:
    
                //Create vector with defined size, zero if not defined
                vector(int size = 0){
                    vlen = size;
                    vlist = new T[size];
    
                    //Check storage
                    assert(vlist != 0);
                }
    
                //Create vector with defined size and fill it
                vector(int size, T fill){
                    vlen = size;
                    vlist = new T[size];
    
                    //Check storage
                    assert(vlist != 0);
    
                    for(int i = 0; i < size; i++){
                        vlist[i] = fill;
                    }
                }
    
                //Copy constructor
                vector(const vector<T>& vector2){
                    vlist = new T[vlen = vector2.vlen];
    
                    //Check storage
                    assert(vlist != 0);
    
                    //Copy elements
                    for(int i = 0; i < vector2.vlen; i++){
                        vlist[i] = vector2.vlist[i];
                    }
                }
    
                //Vector's capacity
                int length() const{
                    return vlen;
                }
    
                //Resize vector's capacity
                void resize(int resizeto){
    
                    /*If the new size is bigger than the old size copy all
                    elements, else copy only new size elements*/
                    int num = resizeto < vlen ? resizeto : vlen;
                    T* newlist = new T[resizeto];
    
                    //Check storage
                    assert(newlist != 0);
    
                    //Loop through elements and copy them
                    for(int i = 0; i < num; i++){
                        newlist[i] = vlist[i];
                    }
    
                    //Delete old storage
                    delete[] vlist;
    
                    //Reassign storage
                    vlen = resizeto;
                    vlist = newlist;
                }
    
                //Fill vector with desired element
                void fill(T fill){
                    for(int i = 0; i < vlen; i++){
                        vlist[i] = fill;
                    }
                }
    
                //Assignment operator
                vector& operator=(const vector<T> &vector2){
    
                    //Check adress to prevent assigning to self
                    if(this!= &vector2){
    
                        /*Delete vector list and assign a new one with the same
                        size*/
                        delete[] vlist;
                        vlist = new T[vlen = vector2.vlen];
    
                        //Check storage
                        assert(vlist != 0);
    
                        //Copy vector components
                        vlen = vector2.vlen;
                        for(int i = 0; i < vlen; i++){
                            vlist[i] = vector2.vlist[i];
                        }
                    }
                    return *this;
                }
    
                //Index operator
                T& operator[](int vindex){
    
                    /*Index must be positive or zero and smaller or equal than
                    vector's length*/
                    if(vindex < 0 || vindex >= vlen){
                        std::cerr << "Illegal vector index: " << vindex
                        << ". Max index = "<< vlen -1 << std::endl;
                        assert(vindex < 0);
                        assert(vindex >= vlen);
                    }
                    return vlist[vindex];
                }
    
                //Constant overloaded index operator
                const T& operator[](int vindex) const{
    
                    /*Index must be positive or zero and smaller or equal than
                    vector's length*/
                    if(vindex < 0 || vindex >= vlen){
                        std::cerr << "Illegal vector index: " << vindex
                        << ". Max index = "<< vlen -1 << std::endl;
                        assert(vindex < 0);
                        assert(vindex >= vlen);
                    }
                    return vlist[vindex];
                }
    
                //Free memory and storage
                ~vector(){
                    delete[] vlist;
                    vlen = 0;
                    vlist = 0;
                }
    
            private:
                T* vlist;
                int vlen;
        };
    
        //IOSTREAM operators
    
        template <class T>
        std::ostream& operator<<(std::ostream& os, const vector<T> &vec){
            if(vec.length() == 0) return os << "(0 size vector)" << std::endl;
            int i = 0;
            os << "(";
            for(i = 0; i < vec.length() - 1; i++){
                os << vec[i] << ", ";
            }
            os << vec[i] << ")" << std::endl;
            return os;
        }
    
        template <class T>
        std::istream& operator>>(std::istream& is, vector<T> &vec){
            if(vec.length() == 0){
                std::cerr << "Cannot take input, vector size = 0. Min size = 1"
                << std::endl;
    
            }
            int i = 0;
            for(i = 0; i < vec.length(); i++){
                is >> vec[i];
            }
            return is;
        }
    }
    
    #endif // MUT_VECTOR_H
    I think I should finish reading my C++ books before trying something this big... xD

  10. #10
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Templated class and iostream overloading

    Quote Originally Posted by beta3designs View Post
    Ok thanks, I know sometimes I should use standard code, but I wanted to do it to learn too... I'm a newbie C++ programmer and I still have to learn a lot... so that's why I wanted to write it myself, so I could learn from my own mistakes.
    Don't try and take on too many new things at the same time, otherwise you'll get swamped by errors and concepts that you don't understand. Re-invent vector is you wish, as a learning exercise, but I think it would be better done as a separate exercise from your maths classes.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  11. #11
    Join Date
    Jan 2004
    Location
    Düsseldorf, Germany
    Posts
    2,401

    Re: Templated class and iostream overloading

    A small comment on the code:
    Quote Originally Posted by beta3designs View Post
    Code:
    namespace mut{
        template <class T=int> //Default vector storage is int
        class vector{
            public:
    
                //Create vector with defined size, zero if not defined
                vector(int size = 0) {
                    // ...
    Such constructors should always be declared as explicit (using the explicit keyword), to prevent implicit conversion of an integer into a vector. It would be very counter-intuitive if 5 would be implicitly converted to a vector of size 5.

    So, once you opened your C++ book again, look for explicit in the index
    More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason - including blind stupidity. --W.A.Wulf

    Premature optimization is the root of all evil --Donald E. Knuth


    Please read Information on posting before posting, especially the info on using [code] tags.

  12. #12
    Join Date
    Jun 2009
    Posts
    5

    Re: Templated class and iostream overloading

    thanks for the tips

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured