13

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.

Community
  • 1
  • 1
CloudyTrees
  • 711
  • 2
  • 10
  • 20
  • Where's your definition for swap? This is probably the problem. – zneak Jan 02 '14 at 01:20
  • @zneak. Oh, I implemented out of the template. In case you need to see it `template void swap(node& a, node& b){ std::swap(a.left, b.left); std::swap(a.right, b.right); std::swap(a.value, b.value); }` – CloudyTrees Jan 02 '14 at 01:22
  • Your first snippet looks right to me... "Yet the linker complained." fix that, instead of breaking your code further ;P – Lightness Races in Orbit Jan 02 '14 at 01:27

2 Answers2

9

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);
}
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • 1
    Yes that works. Thanks. But I'm still wondering why the MSDN code works in VC++ but not under clang. – CloudyTrees Jan 02 '14 at 01:52
  • 14
    @CloudyTrees: The rule clang is using to block it is: C++ 2011 [temp.local] Paragraph 6: __A template-parameter shall not be redeclared within its scope (including nested scopes). A template- parameter shall not have the same name as the template name.__ This can be found in the [clang source code](http://clang.llvm.org/doxygen/SemaTemplate_8cpp_source.html) within the `Sema::DiagnoseTemplateParameterShadow` method. – Bill Lynch Jan 02 '14 at 02:04
0

In case you are making a friend function, you have to write template<class datatype> during function declaration (inside the class). Make sure to use different template parameter names such as:

template <class t>
class Algebra
{
    t a, b;

public:

template<typename os>
friend istream& operator>>( istream & input, Algebra<os>&obj);

};
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 27 '23 at 11:40