Question

I was trying to compile the following code for the classic copy&swap idiom on my Mac with 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
}

Yet the linker complained. I now understand that I should declare the function as a template. But error would occur if I follow the style as suggested here from 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);
};

I did copy-paste but got the following error:

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.

Is this a clang bug? The MSDN website suggests it works under VC++.

PS: I know that there are two solutions: define the friend function inside the template class as in the Stackoverflow article, or declare in the following way inside the template class:

template <typename U> friend void swap(node<U>&, node<U>&);

But both bother me. The first clusters the declaration of the class while the second grants friendship to swap taking different types.

Update: A third solution is to use forward declaration with specialization:

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>&);
};

This works under clang too.

Was it helpful?

Solution

I believe that this is what you want (which happens to be what you just added to your question as the third option)

#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);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top