为 class 之外的模板实现 operator!= 作为自由函数的正确方法
Correct way to implement operator!= for templates outside of class as a free function
我在 map.hpp
文件中有一个内部 classes 的模板:
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
在 main.cpp
中,我调用了以下命令,到目前为止一切正常:
Map<int, int> x;
// bunch of insertions ...
for (auto it = x.begin; it != x.end(); ++it) {
// Do something with it ...
}
但是,我想将 friend 函数移出 map.hpp
文件并移至包含其他实现的 map.hxx
文件中。
问:是否可以将自由函数移动到 .hxx
文件,如何移动?
我厌倦了在迭代器中将函数声明为友元 class 并在实现文件中执行了以下操作:
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);
}
但是它失败了:
$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)
谢谢!
没有相应匹配项的 friend
声明会将新函数注入封闭的命名空间。这个函数只能通过ADL
找到
做你想做的最简单的方法是在 iterator
class 中留下一个存根实现,并将它转发到外部的 "real" 函数。这保留了 !=
的良好的仅 ADL 查找,它轻松解决了一些棘手的过载问题。辅助函数可以简单地是一个 template<class Iterator>
并且更正常地成为朋友并且具有狭窄的实现,并且不是通过 ADL 而是通过完全限定的查找来找到的。或者它可以是封闭映射的静态成员函数。
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;
};
};
现在您的 .hxx
只需实施 bool Map<blah>::it_equal(blah)
就大功告成了。
我在 map.hpp
文件中有一个内部 classes 的模板:
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
在 main.cpp
中,我调用了以下命令,到目前为止一切正常:
Map<int, int> x;
// bunch of insertions ...
for (auto it = x.begin; it != x.end(); ++it) {
// Do something with it ...
}
但是,我想将 friend 函数移出 map.hpp
文件并移至包含其他实现的 map.hxx
文件中。
问:是否可以将自由函数移动到 .hxx
文件,如何移动?
我厌倦了在迭代器中将函数声明为友元 class 并在实现文件中执行了以下操作:
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);
}
但是它失败了:
$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)
谢谢!
没有相应匹配项的 friend
声明会将新函数注入封闭的命名空间。这个函数只能通过ADL
做你想做的最简单的方法是在 iterator
class 中留下一个存根实现,并将它转发到外部的 "real" 函数。这保留了 !=
的良好的仅 ADL 查找,它轻松解决了一些棘手的过载问题。辅助函数可以简单地是一个 template<class Iterator>
并且更正常地成为朋友并且具有狭窄的实现,并且不是通过 ADL 而是通过完全限定的查找来找到的。或者它可以是封闭映射的静态成员函数。
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;
};
};
现在您的 .hxx
只需实施 bool Map<blah>::it_equal(blah)
就大功告成了。