Thread: template friend operator functions

  1. #1
    Registered User
    Join Date
    Jan 2007
    Posts
    330

    template friend operator functions

    I have a question about template friend functions. Is the declaration in the Stack class correct? It compiles in 2 different compilers, so I guess its correct but what does the '<>' operator mean in this context? its not a template specialization but what is it?

    Code:
    template <typename T, unsigned int N> 
    class Stack 
    {
    public: 
      friend ostream &operator<< <>(ostream &os, const Stack<T, N> &s); 
    
    private: 
      T m_stack[N];
    };
    
    template<typename T, unsigned int N> 
    ostream &operator<<(ostream &os, const Stack<T, N> &s) 
    {
      if (!s.empty()) 
      {
        T *cur = s.m_cur;
        while (cur != s.m_stack) 
        {
          os << *--cur << ' '; 
        }
      }
      return os; 
    }

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by KIBO View Post
    I have a question about template friend functions. Is the declaration in the Stack class correct? It compiles in 2 different compilers, so I guess its correct but what does the '<>' operator mean in this context? its not a template specialization but what is it?
    I had not actually seen that before. But after some experimentation, it seems like it's equivalent to:

    Code:
    template <typename T2, unsigned int N2>
    friend ostream &operator<<(ostream &os, const Stack<T2, N2> &s);
    Where T2=T, N2=N.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    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).

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by anon View Post
    I don't get any linker error -- that code compiles (with a few obvious tweaks).
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    The larch
    Join Date
    May 2006
    Posts
    3,573
    It doesn't compile with GCC (4.4.1):

    8 Untitled1.cpp template-id 'operator<< <>' for 'std::ostream& operator<<(std::ostream&, const Stack<int, 2u>&)' does not match any template declaration
    When <> is taken out:
    8 Untitled1.cpp [Warning] friend declaration 'std::ostream& operator<<(std::ostream&, const Stack<T, N>&)' declares a non-template function
    (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
    and a linker error.

    Of course, the compiler may be wrong.
    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).

  6. #6
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Compiles with GCC 4.5.0:

    Code:
    #include <iostream>
    
    using namespace std;
    
    template <typename T, unsigned int N>
    class Stack;
    
    template<typename T, unsigned int N>
    ostream &operator<<(ostream &os, const Stack<T, N> &s)
    {
      if (!s.empty())
      {
        T *cur = s.m_cur;
        while (cur != s.m_stack)
        {
          os << *--cur << ' ';
        }
      }
      return os;
    }
    
    template <typename T, unsigned int N>
    class Stack
    {
    public:
      friend ostream &operator<< <>(ostream &os, const Stack<T, N> &s);
    
    private:
      T m_stack[N];
    };
    
    int main()
    {
        Stack<int, 10> stack;
    }
    When you take out the <> you get these errors:

    /home/daemn/Temporary/asdasdasda/main4.cpp|26|warning: friend declaration ‘std:stream& operator<<(std:stream&, const Stack<T, N>&)’ declares a non-template function|
    /home/daemn/Temporary/asdasdasda/main4.cpp|26|note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) |
    /home/daemn/Temporary/asdasdasda/main4.cpp||In function ‘int main()’:|
    /home/daemn/Temporary/asdasdasda/main4.cpp|34|warning: unused variable ‘stack’|
    ||=== Build finished: 1 errors, 2 warnings ===|
    So it's basically short-hand?
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  7. #7
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I think it is the same as here:

    Code:
    #include <iostream>
    
    template <class T>
    void foo(const T& )
    {
        std::cout << "T\n";
    }
    
    template <>
    void foo<>(const int& ) //or void foo<int>(const int&)
    {
        std::cout << "<int>\n";
    }
    
    void foo(int )
    {
        std::cout << "int\n";
    }
    
    int main()
    {
        foo(3);
        foo<>(3); //indicates desire to use a template function
    }
    Essentially repeating the type appears to be optional.
    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).

  8. #8
    Registered User
    Join Date
    Jan 2007
    Posts
    330
    Quote Originally Posted by brewbuck View Post
    I had not actually seen that before. But after some experimentation, it seems like it's equivalent to:

    Code:
    template <typename T2, unsigned int N2>
    friend ostream &operator<<(ostream &os, const Stack<T2, N2> &s);
    Where T2=T, N2=N.
    This is true, but this form does not compile on somewhat older compilers like visualC++ 2005 and BCbuilder6.

    The operator<< <>() together with forward declares seems to work on more compilers while they are both standard C++.
    I was more wondering about how I should read the operator<< <>() syntax.

  9. #9
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I had not actually seen that before. But after some experimentation, it seems like it's equivalent to:

    Code:
    template <typename T2, unsigned int N2>
    friend ostream &operator<<(ostream &os, const Stack<T2, N2> &s);
    I may be mistaken, but this declares operator<< a friend for any Stack instantiation, whereas other forms limit the friendship only to one particular instantiation (not that it should matter at all).

    However, one might need to be careful, for example, to avoid declaring A<int> a friend of B<float>, where the intent was to allow friendship only for A<float>.
    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).

  10. #10
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Ah, template friends, the last bastion of cross-compiler syntax confusion.

    Code:
    template <typename T>
    void fn4(const T& t);
    
    template <typename T>
    struct Ex
    {
      // Any instantiation of Ex is friend to any instantiation of fn1.
      // This also declares the free function template fn1 in Ex's enclosing scope,
      // but the declaration is not visible to qualified lookup.
      template <typename U>
      friend void fn1(const U& u);
    
      // Any given instantiation Ex<C> is friend to the non-template function fn2(const C&).
      // You'd have to declare and define a separate function for every instantiation, though.
      // You could define this function inline right here to make this work.
      // This also declares the free function fn2 in Ex's enclosing scope, but the declaration is
      // not visible to qualified lookup.
      friend void fn2(const T& t);
    
      // Error. This tries to friend a specialization of the function template fn3, but there is no
      // such function template declared. However, due to the way some compilers (e.g. VC++)
      // parse templates, this might actually work if the template fn3 is declared before Ex is
      // instantiated. GCC, however, will refuse to compile this.
      friend void fn3<>(const T& t);
    
      // Any given instantiation Ex<C> is friend to the specialization fn4<C> of the function
      // template declared at the top of this code.
      friend void fn4<>(const T& t);
    };
    Now substitute "operator <<" for "fnx" and you've got the original code in its variants. Operator names are just normal function names, but they tend to confuse the issue.
    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

  11. #11
    Registered User
    Join Date
    Jan 2007
    Posts
    330
    Quote Originally Posted by CornedBee View Post
    Ah, template friends, the last bastion of cross-compiler syntax confusion.

    Code:
    template <typename T>
    void fn4(const T& t);
    
    template <typename T>
    struct Ex
    {
      // Any instantiation of Ex is friend to any instantiation of fn1.
      // This also declares the free function template fn1 in Ex's enclosing scope,
      // but the declaration is not visible to qualified lookup.
      template <typename U>
      friend void fn1(const U& u);
    
      // Any given instantiation Ex<C> is friend to the non-template function fn2(const C&).
      // You'd have to declare and define a separate function for every instantiation, though.
      // You could define this function inline right here to make this work.
      // This also declares the free function fn2 in Ex's enclosing scope, but the declaration is
      // not visible to qualified lookup.
      friend void fn2(const T& t);
    
      // Error. This tries to friend a specialization of the function template fn3, but there is no
      // such function template declared. However, due to the way some compilers (e.g. VC++)
      // parse templates, this might actually work if the template fn3 is declared before Ex is
      // instantiated. GCC, however, will refuse to compile this.
      friend void fn3<>(const T& t);
    
      // Any given instantiation Ex<C> is friend to the specialization fn4<C> of the function
      // template declared at the top of this code.
      friend void fn4<>(const T& t);
    };
    Now substitute "operator <<" for "fnx" and you've got the original code in its variants. Operator names are just normal function names, but they tend to confuse the issue.
    Maybe im blind but whats the difference between fn3 and fn4?

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by KIBO
    Maybe im blind but whats the difference between fn3 and fn4?
    Notice that fn4 is declared at the top.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User
    Join Date
    Jan 2007
    Posts
    330
    Quote Originally Posted by laserlight View Post
    Notice that fn4 is declared at the top.
    ah yeah thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  2. Replies: 8
    Last Post: 07-24-2006, 08:14 AM
  3. error: template with C linkage
    By michaels-r in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2006, 08:11 AM
  4. Declare a template class as a friend?
    By AH_Tze in forum C++ Programming
    Replies: 11
    Last Post: 05-19-2004, 09:24 PM
  5. oh me oh my hash maps up the wazoo
    By DarkDays in forum C++ Programming
    Replies: 5
    Last Post: 11-30-2001, 12:54 PM