Reputation: 1
I want to define freestanding operators (op==, op<, etc.) for my iterator class, but I'm struggling with the proper syntax:
template<class A>
class Container {
public:
template<class B>
class Iterator {
public:
explicit Iterator(B value) : value_(value) {};
friend bool operator==(const Iterator& lhs, const Iterator& rhs);
private:
A value_;
};
};
// Fails to compile:
template<class A>
template<class B>
bool operator==(const typename Container<A>::Iterator<B>& lhs, const typename Container<A>::template Iterator<B>& rhs) {
return lhs.value_ == rhs.value_;
}
Container<int>::Iterator<double> it1{42.0};
Container<int>::Iterator<double> it2{42.0};
assert(it1 == it2);
Upvotes: 0
Views: 85
Reputation: 1
First things first, the declaration for the operator==
that you have(inside the class) is for a non-member nontemplate operator. So you can't implement it the way you're doing outside the class.
There are different ways of solving this.
One way to solve this is by making the overloaded operator==
a template and defining it inside the class as shown below. Note that the operator==
is still a non-member.
Also note the use of typename
and template
keyword to tell the compiler that Iterator
is a type and a template. This is also explained here.
template<typename A>
struct Container{
template<class B>
class Iterator {
public:
explicit Iterator(B value) : value_(value) {};
//definition for a nonmember template version
//------------------vvv-------------vvv-------->default arguments used
template<typename U = A, typename V = B>
//---------------------------vvvvvvvv---------->typename used here
friend bool operator==(const typename Container<U>::template Iterator<V>& lhs,
const typename Container<U>::template Iterator<V>& rhs)
//--------------------------------------------------^^^^^^^^------------------>template used here
{
return lhs.value_ == rhs.value_;;
}
private:
B value_;
};
};
Container<int>::Iterator<double> it1{42.0}, it2{42.0};
int main()
{
assert(it1 == it2);
}
Second option is to keep the opearator==
as a nontemplate as shown below:
template<typename A>
struct Container{
template<class B>
class Iterator {
public:
explicit Iterator(B value) : value_(value) {};
//declaration for a nonmember nontemplate version
//---------------------------vvvvvvvv------------------------------------------>typename used here
friend bool operator==(const typename Container<A>::template Iterator<B>& lhs,
const typename Container<A>::template Iterator<B>& rhs);
//--------------------------------------------------^^^^^^^^------------------>template used here
private:
B value_;
};
};
//implement the nonmember nontemplate version
bool operator==(const Container<int>::Iterator<double>&lhs, const Container<int>::Iterator<double>&rhs)
{
return lhs.value_ == rhs.value_;
}
Container<int>::Iterator<double> it1{42.0}, it2{42.0};
int main()
{
assert(it1 == it2);
}
Upvotes: 1