2

I want to add a iterator class type for my vector class,and I declare some compare operator as friend function of iterator class.but it didnt complie correctly,I did forward declaration.

template<class object>class vector;
template<class object>
bool operator<(typename vector<object>::const_iterator& lhs, typename vector<object>::const_iterator& rhs);

template<class object>class vector {
protected:
    //some member 
public:
    class const_iterator {
        friend bool operator< <>(const_iterator& lhs, const_iterator& rhs);
        friend bool operator> <>(const_iterator& lhs, const_iterator& rhs);
        //...
    };
};

compiler said no matching overloaded function found,I use vs2019.I guess something wrong with forward declaration.

and another question is,I notice some people use this form when declare friend function inside class.

class myclass{
    friend void foo<T>(T t);
    //...
}

but when declare a operator as friend it's different

friend bool operator< <>(const myclass& lhs, const myclass& rhs);

I wonder what's the difference between these two.

please help me,thanks a lot.

codesavesworld
  • 587
  • 3
  • 10
  • 2
    One question per stackoverflow.com question, please. – Sam Varshavchik Nov 13 '19 at 03:44
  • @Chipster - sorry, I tend to fail the language-lawyer test sometimes, probably shouldn't use that word. I can call an instance of a function template like this `my_func(42)`. But if the compiler can deduce the template arguments from the function arguments, I can say this `my_func<>(42)`. That's what that line is doing, just with a function signature. – parktomatomi Nov 13 '19 at 04:28
  • @parktomatomi Oh, got you. I understand now. –  Nov 13 '19 at 04:30
  • @zxy1122 The declarations you provided compiles just fine on VS 2019 for me on VS 2019. Can you clarify on what code you wrote the triggered the error? – parktomatomi Nov 13 '19 at 07:22

1 Answers1

1

In your forward declaration

template<class object>
bool operator<(typename vector<object>::const_iterator&, 
               typename vector<object>::const_iterator&);

const_iterator is in the non-deduced context, i.e. the compiler will not be able to deduce int for object in the following call:

vector<int>::const_iterator c1;
vector<int>::const_iterator c2;

c1 < c2;

I can suggest two solutions.

  1. The simplest one: omit your forward declarations and provide a definition for operator< inside the body of const_iterator:

    friend bool operator<(const_iterator& lhs, const_iterator& rhs) {
        ... return ... ;        
    }
    
  2. If you can't define operator< inside const_iterator, use CRTP to turn a non-deduced context into a deduced one:

    template<class derived>
    struct const_iterator_crtp {};
    
    template<class derived>
    bool operator<(const_iterator_crtp<derived>&,
                   const_iterator_crtp<derived>&);
    
    template<class object>
    struct vector {
        struct const_iterator : const_iterator_crtp<const_iterator> {
            using base = const_iterator_crtp<const_iterator>;
            friend bool operator< <>(base&, base&);
        private: 
            int priv;
        };
    };
    
    template<class derived>
    bool operator<(const_iterator_crtp<derived>& lhs, 
                   const_iterator_crtp<derived>& rhs)
    {
        auto& l = static_cast<derived&>(lhs);  // these static_cast's are safe
        auto& r = static_cast<derived&>(rhs);
        return l.priv < r.priv;
    }
    

Is the operator< a function template in the first solution? Why we don't need a <> after operator<?

  1. It is not a template. You don't need <> in this definition.

  2. You forward declare a template first. Without <>, a friend declaration introduces a non-template function. A non-template function, even if it has the same name as template one (non-template and template functions can overload!), should be defined somewhere. You'll get a link error without such a definition. To override the default behavior and to refer to the function template that was forward declared earlier, you add <>.

Evg
  • 25,259
  • 5
  • 41
  • 83
  • thanks ,is the operator < a function template in the first solution? why we dont need a <> after operator< .I'm a little confused. – codesavesworld Nov 13 '19 at 11:36
  • @zxy1122, corrected the answer after [this question](https://stackoverflow.com/questions/58837772/friend-function-with-a-definition-template-or-non-template). – Evg Nov 13 '19 at 13:38