Reputation: 793
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.
Upvotes: 2
Views: 204
Reputation: 26292
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.
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 ... ;
}
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<>
afteroperator<
?
It is not a template. You don't need <>
in this definition.
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 <>
.
Upvotes: 1