Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declaring a class template as a friend of a class

Tags:

c++

oop

templates

I am trying to construct a generic handle class following Moo and Kernig's Accelerated C++ (pp. 257-257). However, in order to call the clone-function of the base class I need to make the generic Handle-class a friend of Base.

The example below gives me the errors:

main.cpp:30:18: error: template argument required for ‘class Handle’
     friend class Handle;
                  ^
main.cpp:30:5: error: friend declaration does not name a class or function
     friend class Handle;
     ^
main.cpp: In instantiation of ‘Handle<T>& Handle<T>::operator=(const Handle<T>&) [with T = Base]’:
main.cpp:42:7:   required from here
main.cpp:33:19: error: ‘virtual Base* Base::clone() const’ is protected
     virtual Base *clone() const { return new Base; }

What is the proper notation for making Handle a friend to Base?


#include <iostream>

template <class T>
class Handle
{
  public:
    Handle() : p(0) {}
    Handle &operator=(const Handle &);
    ~Handle() { delete p; }

    Handle(T *t) : p(t) {}

  private:
    T *p;
};

template <class T>
Handle<T> &Handle<T>::operator=(const Handle &rhs)
{
    if (&rhs != this)
    {
        delete p;
        p = rhs.p ? rhs.p->clone() : 0;
    }
    return *this;
};

class Base
{
    friend class Handle; ///this fails

  protected:
    virtual Base *clone() const { return new Base; }

  private:
    int a;
};

main()
{
    Handle<Base> h;
    h = new Base;

    return 0;
}
like image 877
BillyJean Avatar asked Jan 19 '26 10:01

BillyJean


1 Answers

The problem is that Handle is not a class; it is a class template. When you say friend class Handle, it looks for some class named Handle, and fails to find it.

The proper syntax to make every member of a template a friend is to make the friend declaration a template:

class Base
{
    template <typename> friend class Handle;
    // ...
};

This is what you asked for, but I don’t think it’s what you want. Given on your example, you don’t actually need to make the generic Handle a friend of Base, but only the specific one which uses Base. This can be accomplished with:

class Base
{
    friend class Handle<Base>;
    // ...
};
like image 107
Daniel H Avatar answered Jan 21 '26 02:01

Daniel H