template friend functions of template class

后端 未结 4 1431
庸人自扰
庸人自扰 2021-01-13 07:12

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

#include 

template

        
相关标签:
4条回答
  • 2021-01-13 07:37

    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;
    }
    
    0 讨论(0)
  • 2021-01-13 07:37

    I managed to get the following work

    #include <iostream>
    
    template<class T>
    class MyVar;
    
    template<class T>
    void printVar(const MyVar<T>& var);
    
    template<class T>
    void scanVar(MyVar<T>& var);
    
    template<class T>
    class MyVar
    {
        int x;
        friend void printVar<T>(const MyVar<T>& var);
        friend void scanVar<T>(MyVar<T>& var);
    };
    
    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;
    }
    

    UPD: http://en.cppreference.com/w/cpp/language/friend talks about a similar case with operators under "Template friend operators":

    A common use case for template friends is declaration of a non-member operator overload that acts on a class template, e.g. operator<<(std::ostream&, const Foo<T>&) for some user-defined Foo<T>

    Such operator can be defined in the class body, which has the effect of generating a separate non-template operator<< for each T and makes that non-template operator<< a friend of its Foo<T>

    ...

    or the function template has to be declared as a template before the class body, in which case the friend declaration within Foo<T> can refer to the full specialization of operator<< for its T

    0 讨论(0)
  • 2021-01-13 07:37

    This one compiles on MSVC2013. Basicly adds the forward declarations to class and functions before the friend

    template<class T>   class MyVar ; // class forward declaration
    
    template<class T> ; // function forward declarations
    void printVar(const MyVar<T>& var);
    template<class T>
    void scanVar(MyVar<T>& var);
    
    template<class T>
    class MyVar
    {
        friend void printVar<T>(const MyVar<T>&);
        friend void scanVar<T>(MyVar<T>&);
        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 main1(void)
    {
        MyVar<Foo> a;
        scanVar(a);
        printVar(a);
        return 0;
    }
    
    0 讨论(0)
  • 2021-01-13 07:41

    Well there is a solution that is both simple and involving separation between declaration & definition of the friend function. In the declaration of the friend function (inside the class) you have to give a different template param from the one the class accepts (and it make sense cause this function is not a member of this class).

    template<class T>
    class MyVar
    {
        int x;
    
        template<typename Type>
        friend void printVar(const MyVar<Type> & var);
    
        template<typename Type>
        friend void scanVar(MyVar<Type> & var);
    };
    
    template<typename T>
    void printVar(const MyVar<T> & var) {
    
    }
    
    template<typename T>
    void scanVar(MyVar<T> & var) {
    
    }
    

    No forward declaration needed, as well as there is a separation of declaration & definition.

    0 讨论(0)
提交回复
热议问题