简体   繁体   中英

Declaring a class template as a friend of a class

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;
}

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>;
    // ...
};
friend class Handle; ///this fails

That fails since Handle is class template, not a class. Handle<Base> is a class. Use

friend class Handle<Base>;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM