Я пытался скомпилировать следующий код для классическая копия&идиома своп на моем Mac с Clang 3.3
template<typename T> class node{
private:
node<T>* left;
node<T>* right;
T value;
public:
friend void swap(node<T>&, node<T>&);
// other stuff
}
И все же компоновщик пожаловался. Теперь я понимаю, что должен объявить функцию как шаблон. Но ошибка произойдет, если я буду следовать предложенному стилю Вот из MSDN:
template <class T> class Array {
T* array;
int size;
public:template<class T>
//...
template <class T>
friend Array<T>* combine(Array<T>& a1, Array<T>& a2);
};
Я сделал copy-paste, но получил следующую ошибку:
te.cpp:33:19: error: declaration of 'T' shadows template parameter
template<class T>
^
te.cpp:4:17: note: template parameter is declared here
template <class T> class Array {
^
1 error generated.
Это лягушка? Сайт MSDN предполагает, что он работает под VC ++.
PS: я знаю, что есть два решения: определить функцию друга внутри класса шаблона, как в статье Stackoverflow, или объявить следующим образом внутри класса шаблона:
template <typename U> friend void swap(node<U>&, node<U>&);
Но оба беспокоят меня. Первый кластеризует объявление класса, а второй дает дружбу для обмена разными типами.
ОбновитьТретье решение — использовать предварительное объявление со специализацией:
template <typename T> class node;
template <typename T> void swap (node<T>&, node<T>&);
template <typename T> class node{
//...
friend void swap<> (node<T>&, node<T>&);
};
Это работает под Clang тоже.
Я полагаю, что это то, что вы хотите (а именно то, что вы только что добавили в свой вопрос в качестве третьего варианта)
#include <utility>
template <typename T> class node;
template <typename T> void swap(node<T> & a, node<T> & b);
template<typename T> class node {
private:
node<T>* left;
node<T>* right;
T value;
public:
friend void swap<>(node<T>&, node<T>&);
};
template <typename T> void swap(node<T> & a, node<T> & b) {
std::swap(a.left, b.left);
std::swap(a.right, b.right);
std::swap(a.value, b.value);
}
int main() {
node<int> x, y;
swap(x, y);
}
Других решений пока нет …