2

SunStudioでテンプレートクラスにテンプレートフレンドを与えることに問題があります。コードはGNUG++(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.

これはSunStudioC ++の問題ですか、それとも無効なC ++(GCCで引き続き受け入れられ、警告を表示しません-Wall -pedantic)ですか?標準に準拠し、GCCとSun Studioの両方でコンパイルされるようにコードを変更するエレガントな方法はありますか?

よろしくお願いします!

4

2 に答える 2

3

「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 {};
于 2011-10-31T13:58:37.583 に答える
0

Sunのコンパイラにはいくつかの問題がある傾向があり、g++などのコンパイラよりも更新頻度が低いことは確かです。この場合、問題は、グローバルテンプレート関数をシャドウイングするクラスによってコンパイラが混乱することであるように思われます。

ここで問題を直接解決する方法を見つけることができませんでしたが、考えられる回避策があります。

  • クラスのグローバルテンプレートをシャドウイングしないでください。たとえば、グローバルfとフレンドの名前をに変更すると、sunはそれをコンパイルできます。fooこれは、関数が無関係である場合に特に意味があります。
  • Mパブリックインターフェイスを適切と思われる場合に拡張して、友情の必要性を回避します。
于 2011-10-28T14:20:28.480 に答える