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 i开发者_开发技巧s 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!
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 {};
Sun's compiler does tend to have some issues and is certainly updated less frequently than compilers such as g++. In this case, the problem seems to be that the compiler gets confused by the class shadowing the global template function.
I couldn't figure out a way to directly solve your problem here, but there are possible workarounds:
- Just don't shadow the global template in your class. Renaming the global
f
and friend tofoo
for example allows sun to compile it. This especially makes sense if the functions are unrelated. - Avoid the need for friendship by extending the public interface to
M
if that seems appropriate.
精彩评论