1

これは、デフォルトの引数の控除/置換を含むテスト ケースに関するものです。テスト ケースは次のように要約できます。

template <class T, class = typename T::I>h(T){}

template <class T, class = typename T::I>j(T){}

class A
{
   typedef int I;
   friend void h<A>(A);

};

int main()
{
   A a;
   h(a);
   j(a);
}

gcc-4.8.1 は関数 j に対してエラーをスローします。これは、関数 j がフレンドとして宣言されておらず、クラス A に対してプライベートでもなく、プライベート メンバー I (有効な) のアクセス規則に違反しているためです。関数 h はクラス A のフレンドとして宣言されており、プライベート メンバー I にアクセスできるため、gcc は関数 h に対してエラーをスローしません。

Clang は両方の関数でエラーをスローします。関数 j のエラー (宣言されていないフレンドは有効であり、期待どおり) ですが、フレンド関数 h に対してもエラーがスローされます (エラー: 私はクラス A のプライベート メンバーであるため、デフォルトの引数の推定に失敗しました)。これは、フレンド機能のアクセシビリティに違反しています。

コードパスを確認しました。clang はデフォルトの引数を推測できますが、置換を行う前にアクセス ルールをチェックし、エラーが発生します。これをどのように修正する必要があるかについて、誰かがガイダンスを提供できますか?

4

1 に答える 1

1

テンプレート関数の戻り値の型を忘れました。

これで問題は解決するはずです:

template <class T, class = typename T::I> void h(T){}

template <class T, class = typename T::I> void j(T){}

上記のエラーを修正した後も、エラーが発生しました。

  • private セクションで typedef を宣言しました。公開すればいい
  • 関数のフレンドを間違って宣言しました。2 つのテンプレート引数があります (A は完全な型ではないため、A::I は機能しません)。

完全にコンパイル可能な問題は次のとおりです。

#include <iostream>

// Type your code here, or load an example.
template <class T, class = typename T::I> void h(T t){std::cout<<t.a<<std::endl;}

template <class T, class = typename T::I> void j(T t){std::cout<<t.a<<std::endl;}

class A
{
   friend void h<A,int>(A);
   friend void j<A,int>(A);
public :
   typedef int I;
  private :
  int a;

};

int main()
{
   A a;
   h(a);
   j(a);
}
于 2013-09-25T06:27:22.760 に答える