How to properly declare a friend of a nested class of a template class?

前端 未结 2 676
予麋鹿
予麋鹿 2020-12-19 10:54

When I do the following:

template 
class Container
{
public:
    class Iterator
    {
        friend bool operator==(const Iterator& x,         


        
相关标签:
2条回答
  • 2020-12-19 11:13

    The declaration

    friend bool operator==(const Iterator& x, const Iterator& y);
    

    declares a non-template function at the nearest enclosing namespace scope which takes two arguments of type const typename Container<T>::Iterator&. Thus, every time the class Container is instantiated, with some template parameter T, a new overload of operator== is declared.

    Since this operator== is not instantiated from a template, you cannot define it out-of-line as a template. So the only way to define this operator== you have declared is to define it separately for each type for which Container is instantiated. This is almost certainly not desirable.

    The warning warns you that the friend you declared is not a template, which has the undesirable consequences I just explained.

    I believe the correct way to do what you are trying to do is the following:

    template <typename T>
    class Container_Iterator;
    
    template <typename T> bool operator==(const Container_Iterator<T>& x,
                                          const Container_Iterator<T>& y);
    
    template <typename T>
    class Container
    {
    public:
        typedef Container_Iterator<T> Iterator;
    };
    
    template <typename T>
    class Container_Iterator {
      friend bool operator==<T>(const Container_Iterator<T>& x,
                                const Container_Iterator<T>& y);
    };
    
    // btw, don't forget to define operator==
    

    Now we explicitly declare operator== as a template, and each specialization of the iterator declares the corresponding specialization of operator== as its friend.

    0 讨论(0)
  • 2020-12-19 11:34

    It's warning about the fact that it is going to be virtually impossible to define that operator== out-of-class.

    That is to say, that friend declaration befriends a non-template operator== function - for example, Container<Int>::Iterator has as a friend the function

    bool operator==(const Container<Int>::Iterator&, const Container<Int>::Iterator&);
    

    This function is not a template, so there's pretty much no way to define operator== for all possible Containers outside the class template definition.

    If you try to do

    template<class T>
    bool operator==(const Container<T>::Iterator&, const Container<T>::Iterator&);
    

    That's a function template, and doesn't match the friend declaration. (In this case it's even worse, as you can't actually use this operator because T is in a non-deduced context.)

    The warning message suggests one possible fix - first declaring a function template and then befriending a specialization of it. (You'll need to pull Iterator out of the class into its own separate class template so that T can be deduced.) The other possible fix is to just define the function inside the class template definition.

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