I have a following template with inner classes in a map.hpp
file:
template<typename Key_T, typename Mapped_T>
class Map {
// public members of Map ...
class Iterator {
//public members of Iterator ...
friend bool operator!=(const Iterator &i, const Iterator &j) {
return (i.link != j.link);
}
// private members of iterator ...
Node * link;
};
};
#include "map.hxx" //implementation file for member methods is separate
In the main.cpp
I call the following and so far everything works fine:
Map<int, int> x;
// bunch of insertions ...
for (auto it = x.begin; it != x.end(); ++it) {
// Do something with it ...
}
However, I want to move the friend function out of the map.hpp
file and into the map.hxx
file which contains other implementation.
Q: Is it possible to move the free function to a .hxx
file and how?
I tired declaring the function as a friend in the Iterator class and did the following in the implementation file:
template<typename Key_T, typename Mapped_T>
bool operator!=(const typename Map<Key_T, Mapped_T>::Iterator & i,
const typename Map<Key_T, Mapped_T>::Iterator & j) {
return (i.link != j.link);
}
However it failed with:
$clang++ -std=c++11 -stdlib=libc++ -Wall -Wextra -g main.cpp
Undefined symbols for architecture x86_64:
"shiraz::operator!=(shiraz::Map<int, int>::Iterator const&, shiraz::Map<int, int>::Iterator const&)", referenced from:
_main in main-3oCRAm.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Thanks!
A friend
declaration without a corresponding match will inject a new function into the enclosing namespace. This function can only be found via ADL
The easiest way to do what you want is to leave a stub implementation in the iterator
class, and have it forward to a "real" function outside. That keeps the nice ADL-only lookup of !=
, which solves some thorny overload problems easily. The helper function can simply be a template<class Iterator>
and be friended more normally and have a narrow implementation, and not be found via ADL but rather with a fully qualified lookup. Or it could be a static member function of the enclosing map.
template<typename Key_T, typename Mapped_T>
class Map {
class Iterator;
static bool it_equal( Iterator const&, Iterator const& );
class Iterator {
friend class Map;
friend bool operator!=(const Iterator &i, const Iterator &j) {
return !Map::it_equal(i,j);
}
friend bool operator==(const Iterator &i, const Iterator &j) {
return Map::it_equal(i,j);
}
Node * link;
};
};
now your .hxx
simply implements bool Map<blah>::it_equal(blah)
and you are done.