I am trying to place a friend function of a template class named sort in its own header file. I keep getting errors when compiling my test program. I have tried different things to fix it, but nothing works. My experience with template classes is limited as is my knowledge about the finer points of header files. Can anyone see what the problem is? Thanks in advance.

Here are the errors from g++:

In file included from UList.h:15,
from test.cpp:1:
sortBS.h:15: error: variable or field âsortâ declared void
sortBS.h:15: error: âUListâ was not declared in this scope
sortBS.h:15: error: expected primary-expression before â>â token
sortBS.h:15: error: â::UListâ has not been declared
sortBS.h:15: error: expected primary-expression before â>â token
sortBS.h:15: error: âobjâ was not declared in this scope

The code below is what I currently have after trying to fix the problem.

Here is the code from the header file, UList.h, for the template class:

#include <vector>
#include <iostream>
#include "sortBS.h"
template <class T>
class UList{

  public:

    template <class U>
    friend std::ostream& operator << (std::ostream&, const UList<U>&);

    template <class U>
    friend void sort (UList<U>&);

    UList (size_t=10);
    virtual ~UList();
    void insert (const T&);
    bool erase (const T&);
    bool find (const T&) const;
    size_t size() const;
    bool empty() const;

  protected:

    std::vector<T> items;  //list of items
};

Here is the code from the header file, sortBS.h, that contains the definition of sort:

#include "UList.h"

template <class U>
void sort (UList<U>::UList<U>& obj){
  U temp;
  for (int i = 1; i < obj.items.size(); ++i){
    for (int index = 0; index < obj.items.size() - i; ++index){
      if (obj[index] > obj[index +1]){
        temp = obj[index];
        obj[index] = obj[index +1];
        obj[index +1] = temp;
      }
    }
  }
}

Dani AI

Generated

Short summary and the safe pattern.

The build errors come from two separate problems: an invalid parameter type in the sort definition (the parser chokes on a scoped/duplicated type) and a circular-include between the two headers. The practical fixes you already found are correct: use the plain parameter type (e.g. UList<U>&) in the definition, and break the include cycle (do not #include the implementation header from inside the class header).

How to arrange things so the friend can live in its own header

  • Forward-declare the class template and the free-function template before you define the class (so the friend declaration can refer to that template rather than inventing a new non-template friend).
  • Inside the class use the “empty-angle-brackets” form so the friend refers to the previously declared template (that tells the compiler “this is the template we declared earlier”).
  • Put the function template definition in its own header that includes UList.h. Do not have UList.h include that implementation header; instead include the implementation header from the translation unit that needs the function (or have the implementation header include UList.h and include only the implementation header where needed).

Minimal corrected example for the separate header (illustrative):

// sortBS.h
#include "UList.h"

template<typename U>
void sort(UList<U>& obj) {
    // implementation; obj.items is accessible because sort is a friend
}

Troubleshooting tips

  • Ensure include guards or #pragma once.
  • Compile with -Wall -Wextra to catch signature mismatches.
  • Avoid writing a scoped parameter like UList<U>::UList<U>& — it is incorrect; use UList<U>&.
  • If you declare friend void sort(UList<T>&); inside the class without a prior template declaration, the compiler treats that as a non-template friend (one ordinary function per specialization), which is not what you want for a separate template definition.

Notes on the thread: was right that the declaration and definition must match; pointed to the forward-declare + empty-<> friend pattern; and ’s final fix (remove the scope qualifier and stop including the implementation header from the class header) is the correct, practical solution.

Recommended Answers

All 3 Replies

declare of sort (UList<U>&) don't match it's define
parameters are not agreement

1. Declare each template friend function before the definition of template class. (#include of the header, as you have will do).

2. Add <> in the friend declarations.

template <class T> class UList ;

template <typename T > void sort( UList<T>& ) ;

template <typename T >
std::ostream& operator << ( std::ostream&, const UList<T>& ) ;


template < typename T >  class UList
{
  public:

    friend std::ostream& operator << [b]<>[/b] ( std::ostream&, const UList<T>& ) ;

    friend void sort [b]<>[/b] ( UList<T>& ) ;
    
    // ...
} ;

See http://www.parashift.com/c++-faq-lite/templates.html#faq-35.16

Thanks for the replies. I found out that I needed to remove the scope resolution in the parameter list in the friend function's definition. Also, the header file containing the definition of the friend function should not have been included in the template class header file.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.