Reputation: 103
So I am trying to create a function that compares two iterators, but I am unsure how to appropriately use the templates. The class
template<typename Key_T, typename Mapped_T>
class Map{...}
The free function
bool operator==(const Map::Iterator &iter1, const Map::Iterator &iter2) {
return (*(iter1.ref->key) == *(iter2.ref->key)) ? true : false; }
I get this error
error: invalid use of template-name ‘cs540::Map’ without an argument list
Then I tried this
template<typename Key_T, typename Mapped_T>
bool operator==(const Map<Key_T,Mapped_T>::Iterator &iter1, const Map<Key_T,Mapped_T>::Iterator &iter2) {...}
and I get this error
error: need ‘typename’ before ‘cs540::Map<Key_T,
Mapped_T>::Iterator’ because ‘cs540::Map<Key_T, Mapped_T>’ is a dependent scope
Upvotes: 0
Views: 384
Reputation: 137310
The error message is telling you that you need to tell the compiler that Map<Key_T,Mapped_T>::Iterator
is a type, by writing typename
in front of it - i.e.,
template<typename Key_T, typename Mapped_T>
bool operator==(const typename Map<Key_T,Mapped_T>::Iterator &iter1,
const typename Map<Key_T,Mapped_T>::Iterator &iter2) { ...}
See Where and why do I have to put the "template" and "typename" keywords? for an explanation why you need to do this.
But that's not going to work for you, either. Everything to the left of ::
is a non-deduced context; for an operator function template to be usable, the compiler must be able to deduce the template arguments from a call, but it cannot do so when the template parameters only appear in non-deduced contexts. The result is that Key_T
and Mapped_T
can never be deduced, and the operator==
will never be used.
Your design appears to be something along the lines of
template<typename Key_T, typename Mapped_T>
class Map{
class Iterator {
// ...
};
// ...
};
The usual approach is to define a non-template friend
operator==
inside the Iterator
definition, i.e.
template<typename Key_T, typename Mapped_T>
class Map{
class Iterator {
// ...
friend bool operator==(Iterator iter1, Iterator iter2) {
return /* ... */;
}
};
// ...
};
A possible alternative approach is to make Iterator
its own class template outside of Map
:
template<typename Key_T, typename Mapped_T>
class MapIterator {
// ...
};
template<typename Key_T, typename Mapped_T>
class Map{
using Iterator = MapIterator<Key_T, Mapped_T>;
};
and now you can write
template<typename Key_T, typename Mapped_T>
bool operator==(MapIterator<Key_T, Mapped_T> iter1, MapIterator<Key_T, Mapped_T> iter2) {
return /* ... */;
}
as Key_T
and Mapped_T
can now be deduced properly.
Upvotes: 3