c++sunstudio

template friend of template class fails in Sun Studio C++


I have a problem with giving a template class a template friend in Sun Studio. The code compiles fine with GNU G++ (4.4.1 and 4.4.3), but fails with Sun Studio C++ (5.9 SunOS_sparc Patch 124863-01 2007/07/25).

Here is a minimal example:

// Forward declarations
template<class T> class M;
template<class T> void f(M<T>, M<T>);

// Define M<T>
template<class T>
class M
{
public:
    void f(M<T>) { }

    friend void ::f<>(M<T>, M<T>);
};

// Define global function f
template<class T>
void f(M<T> a, M<T> b)
{
    a.f(b);
}

M<int> a;

When I try to compile it via CC -c -o t3.o t3.cpp, I get the following error messages:

"t3.cpp", line 12: Warning:  A friend function with template-id name must have a template declaration in the nearest namespace.
"t3.cpp", line 22:     Where: While specializing "M<int>".
"t3.cpp", line 22:     Where: Specialized in non-template code.
"t3.cpp", line 12: Error: Global scope has no declaration for "f".
"t3.cpp", line 22:     Where: While specializing "M<int>".
"t3.cpp", line 22:     Where: Specialized in non-template code.
1 Error(s) and 1 Warning(s) detected.

Is this a problem with Sun Studio C++, or is it invalid C++ (which is still accepted by GCC and gives no warnings with -Wall -pedantic)? Is there an elegant way to change the code such that it is standard compliant and compiles both under GCC and Sun Studio?

Thanks a lot in advance!


Solution

  • Successfully compiled your code using "CC: Sun C++ 5.8 Patch 121017-13 2008/01/02" adding template declaration to a friend:

    template<class T>
    class M
    {
        ...
        template <class A>
        friend void ::f(M<A>, M<A>);
        ...
    };
    

    Following is not an answer to original question but those who is looking why a friend template class causes "Error: Multiple declaration for " error compiling using Sun CC compiler, just add forward declaration for the friend class, like this:

    template <typename T> class B; //will fail without forward declaration
    
    class A
    {
        private:
        template <typename T> friend class B;
    };
    
    template <typename T> class B {};