c++templatesfriendfriend-functiontemplate-function

template friend functions of template class


I have the following template class and template function which intends to access the class' private data member:

#include <iostream>

template<class T>
class MyVar
{
    int x;
};

template<class T>
void printVar(const MyVar<T>& var)
{
    std::cout << var.x << std::endl;
}

template<class T>
void scanVar(MyVar<T>& var)
{
    std::cin >> var.x;
}

struct Foo {};

int main(void)
{
    MyVar<Foo> a;
    scanVar(a);
    printVar(a);
    return 0;
}

To declare the two functions as MyVar<T>'s friend functions, I've tried the following ways inside the declaration of template<class T> class MyVar to declare friendship. None of them works. How should I do?

template<class T> friend void printVar(const MyVar&);
template<class T> friend void scanVar(MyVar&);
// compilation error

template<class T> friend void printVar(const MyVar<T>&);
template<class T> friend void scanVar(MyVar<T>&);
// compilation error

friend void printVar(const MyVar<T>&);
friend void scanVar(MyVar<T>&);
// link error

friend void printVar(const MyVar&);
friend void scanVar(MyVar&);
// link error too

Solution

  • The simplest option is to define the friend within the class:

    template<class T>
    class MyVar
    {
        int x;
    
        friend void printVar(const MyVar & var) {
            std::cout << var.x << std::endl;
        }
        friend void scanVar(MyVar & var) {
            std::cin >> var.x;
        }
    };
    

    The downside is that the functions can only be called through argument-dependent lookup. That's not a problem in your example, but might be a problem if they don't have a suitable argument, or you want to specify the name without calling it.

    If you want a separate definition, then the template will have to be declared before the class definition (so it's available for a friend declaration), but defined afterwards (so it can access the class members). The class will also have to be declared before the function. This is a bit messy, so I'll only show one of the two functions:

    template <typename T> class MyVar;
    template <typename T> void printVar(const MyVar<T> & var);
    
    template<class T>
    class MyVar
    {
        int x;
    
        friend void printVar<T>(const MyVar<T> & var);
    };
    
    template <typename T> void printVar(const MyVar<T> & var) {
        std::cout << var.x << std::endl;
    }