Thread: Overloading templated class operators

  1. #1
    Registered User
    Join Date
    Nov 2006
    Posts
    5

    Overloading templated class operators

    Having some trouble understanding how to overload operators (specifically << and >> ) for
    a templated class.

    Here's what I have in Attribute.h:
    Code:
    #include <iostream>
    
    template <typename T>
    class Primitive
    {
    
        template<typename C> friend istream& operator>>(istream& in, Primitive<C>& p) { in >> p.data; return in; }
        template<typename C> friend ostream& operator<<(ostream& out, const Primitive<C>& p) { out << p.data; return out; }
      
        public:
        
            Primitive(T d) { data=d; }
            Primitive(Primitive& p) { data=p.getData(); }
            ~Primitive(){};
            T getData(){ return data; };
            
        private:
            T data;
        };

    This is the main.cpp I use:
    Code:
    #include <cstdlib>
    #include <iostream>
    #include <Attribute.h>
    
    int main(int argc, char *argv[])
    {
        Attribute<int> aI(5);
        Attribute<string> aS("Bob");
        
        cout<<aI;
              
        system("PAUSE");
    }
    and these are the errors:
    Code:
    In file included from main.cpp:8:
    I:/Dev-Cpp/include/c++/3.4.2/Primitive.h:7: error: expected init-declarator before '&' token
    I:/Dev-Cpp/include/c++/3.4.2/Primitive.h:7: error: expected `;' before '&' token
    I:/Dev-Cpp/include/c++/3.4.2/Primitive.h:8: error: expected init-declarator before '&' token
    I:/Dev-Cpp/include/c++/3.4.2/Primitive.h:8: error: expected `;' before '&' token
    I feel I may be a little over my head as I just got the hang of template classes and functions. I've read the few posts here that I could find with my meager script-fu, but I'm coming up short on understanding. Help?

  2. #2
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    The problem is the templated friends. They're a horror to work with: I can never remember which are even valid C++ and which are not.

    Avoid them.

    Make the operators free template functions and don't declare them friends. The presence of the input operator means that your primitives are not immutable, so you should provide a public setData() function for setting the value of a Primitive object. With that and getData(), you can implement the stream operators without friend access, which is always preferable.

    Note: Never make a function a friend unless you have to. See also the section on object-oriented design in Effective C++, 3rd Edition.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  3. #3
    Registered User
    Join Date
    Nov 2006
    Posts
    5
    So what you're saying is remove the friend qualifier?
    I have a public getData() method and will make a public setData() method, although I was waiting until I had the output operator working.

    I also just realized I was showing two versions of the same program. Primitive.h and Attribute.h are exactly the same, save for the names. I had been working on an Attribute class and came across someone else's similar problem using a Primitive class. Looked just like what I was doing so I tried working with that.

    Anyway, having removed the friend qualifier I'm still getting the same problem:
    Code:
    C:/Dev-Cpp/include/Primitive.h:6: error: expected constructor, destructor, or type conversion before '&' token
    
    C:/Dev-Cpp/include/Primitive.h:6: error: expected `;' before '&' token
    
    C:/Dev-Cpp/include/Primitive.h:11: error: expected constructor, destructor, or type conversion before '&' token
    
    C:/Dev-Cpp/include/Primitive.h:11: error: expected `;' before '&' token
    using:
    Code:
    #include <iostream>
    
    template <typename T>
    class Primitive
    {
        template<typename C> istream& operator>>(istream& in, Primitive<C>& p)
        {
            in << p.setData();
            return in;
            }
        template<typename C> ostream& operator<<(ostream& out, const Primitive<C>& p)
        {
            out << p.getData();
            return out;
            }
    
        public:
    
            Primitive(T d) { data=d; }
            Primitive(Primitive& p) { data=p.getData(); }
            ~Primitive(){};
            T getData(){ return data; };
            void setData(T d) { data = d;}
    
        private:
            T data;
        };
    I'm thinking that I'm putting the definition in the wrong place but every tutorial I can find on the subject uses the friend method.

  4. #4
    Registered User
    Join Date
    Nov 2006
    Posts
    5
    Nevermind, realized I was missing several ';' at the end of my functions. I've fixed that and am left with:
    Code:
    #include <iostream>
    
    template <typename T>
    class Primitive
    {
        public:
            Primitive(){};
            Primitive(T d): data(d) { };
            Primitive(Primitive& p) { data=p.getData(); };
            ~Primitive(){};
            T getData(){ return data; };
            void setData(T d) { data = d;};
            T istream& operator>>(istream& in, Primitive<T>& p)  //Line 13
            {
                in << p.setData();
                return in;
                };
            T ostream& operator<<(ostream& out, Primitive<T>& p)  //Line 18
            {
                out << p.getData();
                return out;
                };
    
        private:
            T data;
        };
    and the errors:
    Code:
    C:/Dev-Cpp/include/Primitive.h:13: error: expected `;' before '&' token
    
    C:/Dev-Cpp/include/Primitive.h:18: error: expected `;' before '&' token

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    You have to specify the std namespace for istream and ostream. You also have to remove the T from the return values of the functions. Finally, you have to move those functions outside of the class, they should not be members or Primitive.

    Actually, that's just a start, also look at the operator>> function, you have to re-do that a little. There might be other errors as well, but start by fixing those.

  6. #6
    Registered User
    Join Date
    Nov 2006
    Posts
    5
    Bingo! I had added 'using namespace std' since my post, but I didn't realize that the functions needed to be out of the class. Works like a charm now, thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 10-19-2008, 12:10 PM
  2. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 05:01 PM
  3. Message class ** Need help befor 12am tonight**
    By TransformedBG in forum C++ Programming
    Replies: 1
    Last Post: 11-29-2006, 11:03 PM
  4. Calling Base Class Operators
    By pianorain in forum C++ Programming
    Replies: 2
    Last Post: 03-10-2005, 10:53 AM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM