Sun Studio C++ 中模板类的模板友元失败

Posted

技术标签:

【中文标题】Sun Studio C++ 中模板类的模板友元失败【英文标题】:template friend of template class fails in Sun Studio C++ 【发布时间】:2011-10-14 14:28:01 【问题描述】:

我在 Sun Studio 中为模板类指定模板朋友时遇到问题。该代码在 GNU G++(4.4.1 和 4.4.3)下编译良好,但在 Sun Studio C++(5.9 SunOS_sparc Patch 124863-01 2007/07/25)下编译失败。

这是一个最小的例子:

// 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;

当我尝试通过CC -c -o t3.o t3.cpp 编译它时,我收到以下错误消息:

"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.

这是 Sun Studio C++ 的问题,还是无效的 C++(仍然被 GCC 接受,-Wall -pedantic 没有给出警告)?是否有一种优雅的方式来更改代码,使其符合标准并在 GCC 和 Sun Studio 下编译?

提前非常感谢!

【问题讨论】:

SunStudio 的问题,很糟糕。查看提升源可以发现许多关于如何解决问题的想法。 谢谢,那我去看看提升源。 我在 boost 源代码中浏览了一下,在我看来,解决这个问题的最有效方法是在 Sun Studio 上使用 #ifdef:不起作用),只需将所需的东西public 替换为protectedprivate,并删除friend 语句。 既然 M::f() 是公开的,为什么还需要朋友声明呢? 出现此问题的“真实”模板有一些私有数据, ::f() 也在使用这些数据。 【参考方案1】:

使用“CC: Sun C++ 5.8 Patch 121017-13 2008/01/02”成功编译您的代码,并将模板声明添加给朋友:

template<class T>
class M

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

以下不是原始问题的答案,而是那些正在寻找为什么朋友模板类会导致“错误:使用 Sun CC 编译器编译的多重声明”错误的人,只需为朋友类添加前向声明,如下所示:

template <typename T> class B; //will fail without forward declaration

class A

    private:
    template <typename T> friend class B;
;

template <typename T> class B ;

【讨论】:

谢谢,这真的帮助了我。 回复:您的第二个答案,我在尝试构建 boost 时遇到了一个相当奇怪的情况。代码类似于:template &lt;typename T&gt; class A; template &lt;typename T, typename U&gt; class A&lt;T(U)&gt; template &lt;typename V&gt; class impl; template &lt;typename V&gt; friend class impl; template &lt;typename V&gt; class impl ; /* ... */ ... 其中嵌套的impl 类会出现Multiple declaration... 错误。我发现解决它的唯一方法是删除前向声明并将朋友声明移动到类主体之后。【参考方案2】:

Sun 的编译器确实存在一些问题,而且更新频率肯定低于 g++ 等编译器。在这种情况下,问题似乎是编译器被遮蔽全局模板函数的类弄糊涂了。

我无法找到直接解决您的问题的方法,但有一些可能的解决方法:

只是不要在您的班级中隐藏全局模板。例如,将全局 f 和朋友重命名为 foo 允许 sun 编译它。如果功能不相关,这尤其有意义。 如果合适的话,可以通过将公共接口扩展到M 来避免建立友谊。

【讨论】:

以上是关于Sun Studio C++ 中模板类的模板友元失败的主要内容,如果未能解决你的问题,请参考以下文章

C++ 提高教程 模板-类模板与友元

c++友元模板单例模式

将派生类的构造函数声明为父类的友元

122.模板与友元

类模板 友元重载形式 各种运算符重载 new delete ++ = +=

Sun Studio 12 中的模板编译错误