Search code examples
c++templatesfriend

Making a template parameter as friend of template class


I am debugging an application which interacts with third party library whose code is not available only header and .so are available. Now I can load it into debugger and check variable values of private member of class declared in third party library but since number of objects are huge, I want to create some mechanism to print it on console which I can analyse later. I came up with something like this

ThirdPartyHeader

class A
{
    private:
    int i;
};

I have not included extra details in above class

Debugprinter.cpp

#include <thirdpartheaders>

template <typename T> class debugprinter
{
    friend class T;
    public :
    void printonconsole()
    {
        T a;
        std::cout << std::endl << a.i << std::endl;
        return;
    }
}

Now I tried to compile above this but it seems that I can't declare undefined type T as friend to my template class and get this error

Error: i is not accessible from x::acc()

Now I can resolve this problem by creating non template debugprinter but just out of curiosity is there a way I can create a template class which would be friend to it's input type parameter?

Thanks


Solution

  • The first thing is that as others mentioned friendship is not symmetric and you are attempting the wrong direction (granting A access to debugprinter<A>. That being said, and just for the sake of people searching through questions:

    In the old version of the standard (C++03) it was impossible to directly declare a template argument as a friend. That restriction was lifted in C++11, although it requires a slightly different syntax:

    template <typename T>
    class test {
       friend T;             // note, not 'friend class T'!!!
    };
    

    Still, in C++03 you could achieve the same behavior by using one extra level of indirection. You cannot befriend a template argument, but you can befriend a dependent type, and by using an identity meta-function you could achieve what you wanted:

    template <typename T>
    struct identity {
       typedef T type;
    };
    template <typename T>
    class test {
       friend class identity<T>::type;
    };