Thread: Templates problem

  1. #1
    Registered User
    Join Date
    Jan 2008
    Posts
    65

    Templates problem

    This code compiles and executes fine in Visual Studio. However, g++ gives me the error messages:
    Code:
    t5.cpp: In function `std::ostream& operator<<(std::ostream&, Foo<T>&) [with T =
       int]':
    t5.cpp:19:   instantiated from here
    t5.cpp:5: `int Foo<int>::t' is private
    t5.cpp:14: within this context
    What am I doing wrong?

    Code:
    #include <iostream>
    
    template<class T>
    class Foo {
        T t;
    public:
        Foo(T tt) : t(tt) {
        }
        template<class U> friend std::ostream& operator<<(std::ostream& os, Foo<T>& f);
    };
    
    template<class T>
    std::ostream& operator<<(std::ostream& os, Foo<T>& f) {
        return os << f.t;
    }
    
    int main() {
        Foo<int> f(0);
        std::cout << f;
        std::cin.get();
        return 0;
    }

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Shouldn't the template parameter match the template name (i.e., shouldn't your function take a Foo<U>)?

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Take the "template class <U>" of of the friend declaration within the templated class Foo. That will make your operator<<() a friend of class Foo<T>.

  4. #4
    Registered User
    Join Date
    Jan 2008
    Posts
    65
    Thanks, that worked. I guess it was compiling in Visual Studio because it isn't very standards-conforming?

  5. #5
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Template friends of templates are tricky business.
    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

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Here's some reading.

    I'd take the last bit of advice (implementing the friend operator within the class) especially seeing that with templates you won't be able to separate the implementation from the declarations anyway.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    In this case I think you'd be better off writing a public 'get' accessor for t and using that, instead of trying to make them friends.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  8. #8
    Registered User
    Join Date
    Jan 2008
    Posts
    65
    Quote Originally Posted by anon View Post
    Here's some reading.

    I'd take the last bit of advice (implementing the friend operator within the class) especially seeing that with templates you won't be able to separate the implementation from the declarations anyway.
    The way I did it wasn't mentioned in the article. Is it one of the other ways of the "several ways to do this"?

    I've encountered yet another situation where one compiler will compile and the other does not.

    This code is pure copy and paste off of the given link.

    Code:
    #include <iostream>
    
    template<typename T> class Foo;  // pre-declare the template class itself
    template<typename T> Foo<T> operator+ (const Foo<T>& lhs, const Foo<T>& rhs);
    template<typename T> std::ostream& operator<< (std::ostream& o, const Foo<T>& x); 
    
    template<typename T>
    class Foo {
    public:
        Foo(const T& value = T());
        friend Foo<T> operator+ <>(const Foo<T>& lhs, const Foo<T>& rhs);
        friend std::ostream& operator<< <>(std::ostream& o, const Foo<T>& x);
    private:
        T value_;
    }; 
    
    int main()
    {
        Foo<int> lhs(1);
        Foo<int> rhs(2);
        Foo<int> result = lhs + rhs;
        std::cout << result;
    
    } 
    
    template<typename T>
    Foo<T>::Foo(const T& value = T())
    : value_(value)
    { }
    
    template<typename T>
    Foo<T> operator+ (const Foo<T>& lhs, const Foo<T>& rhs)
    { return Foo<T>(lhs.value_ + rhs.value_); }
    
    template<typename T>
    std::ostream& operator<< (std::ostream& o, const Foo<T>& x)
    { return o << x.value_; }
    Visual Studio compiles happily and g++ gives the following errors:
    Code:
    t8.cpp:28: error: default argument given for parameter 1 of `Foo<T>::Foo(const T&)'
    t8.cpp:10: error: after previous specification in `Foo<T>::Foo(const T&)'
    So, which should it be? Is this even more proof of the inferiority of Microsoft's compiler?

  9. #9
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    >> So, which should it be? Is this even more proof of the inferiority of Microsoft's compiler?
    Hardly. Examples from that particular FAQ are rarely complete, compilable programs, and you shouldn't take a mishmash of examples and expect it to work. Usually the text is the most informative portion.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Laptop Problem
    By Boomba in forum Tech Board
    Replies: 1
    Last Post: 03-07-2006, 06:24 PM
  2. Questions about Templates
    By Shamino in forum C++ Programming
    Replies: 4
    Last Post: 12-18-2005, 12:22 AM
  3. Replies: 5
    Last Post: 11-07-2005, 11:34 PM
  4. Problem with templates
    By Lazy Student in forum C++ Programming
    Replies: 3
    Last Post: 11-17-2002, 12:57 PM