Search code examples
c++templatesfriend

c++ non-template class friends to a member of template class


I am new using template. As title, I have a non-template classes (Obj and ObjBase) and a template class PItem. I want to let PITem::RefValue() accesses private members in Obj.

I thought below would work:

   template<class T>
   friend int PItem<T>::getValue();

It doesn't:

error C2248: 'Obj::getValue': cannot access private member declared in class 'Obj'

note: see reference to function template instantiation 'int PItem::getValue(void)' being compiled

Compiler complaints:

   if (ptr) return ptr->getValue();
class ObjBase
{
public:
    ObjBase() {}
    ~ObjBase(){}
protected:
    int  value{0};
};

class Obj : public ObjBase
{
    template<class T>
    class PItem;

    template<class T>
    friend int PItem<T>::getValue();

public:
    Obj(int i) { value = i; };
    ~Obj() {};

private:
    int getValue()
    {
        return value;
    }
};

template<typename T>
class PItem
{
public:
    PItem(T* t) { ptr = t; }
    ~PItem() {}
    int getValue() {
        if (ptr) return ptr->getValue();
        return -1;
    }
    T* ptr;
};

Solution

  • You're declaring a nested class template PItem inside Obj, then the friend declaration refers to it, not the one defined in globle scope.

    You should remove the nested class template declaration, and move the definition of PItem before the definition of Obj; because the friend declaration requires PItem to be complete type.

    template<typename T>
    class PItem
    {
    public:
        PItem(T* t) { ptr = t; }
        ~PItem() {}
        int getValue() {
            if (ptr) return ptr->getValue();
            return -1;
        }
        T* ptr;
    };
    
    class Obj : public ObjBase
    {
    
        template<class T>
        friend int PItem<T>::getValue();
    
    public:
        Obj(int i) { value = i; };
        ~Obj() {};
    
    private:
        int getValue()
        {
            return value;
        }
    };
    

    LIVE