私はかなり面白い行動だと思う何かに気づきました。
私ができるだけ一般的にしようとした次のサンプルコードを考えてみましょう。
class Base
{
public:
virtual void func() {}
};
class Subclass : public Base
{
public:
void func() {}
};
class ApplyingClass
{
public:
static void callFunc(Base& base) { base.func(); }
private:
template <class T>
static void callFunc(T& t) { t.func(); }
};
int main()
{
Subclass s;
Base& b = s;
// Error: ApplyingClass::callFunc(T& t) with T=Subclass is private.
ApplyingClass::callFunc(s);
// works
ApplyingClass::callFunc(b);
return 0;
}
main()内では、テンプレートメソッドが存在するため、コンパイラはテンプレート「ApplyingClass :: callFunc(T&t)」を関数呼び出し「ApplyingClass :: callFunc(s)」に適切であると見なしてスローするようです。クラスの外部からメソッドにアクセスできないため、エラーが発生します。
これは論理的に思えますが、メソッドのシグネチャが適合し、これが唯一のアクセス可能な適合メソッドであるため、コンパイラが引き続き「ApplyingClass :: callFunc(Base&base)」を使用しようとすると予想しました。
私の主張をもう少し詳しく説明します。ApplyingClassからプライベートテンプレートメソッドを削除した場合、main()内の両方の関数呼び出しが有効になります。
私の質問は、これがC ++仕様の一部なのか、それともコンパイラ固有の動作なのかということです(これは、Visual Studio 2017 ver 15.5.7コンパイラを使用してテストされました)。
ここでエラーを発行するのは有効なC ++です。
[class.member.lookup]を参照してください:
オーバーロードされた関数の名前が明確に見つかった場合、アクセス制御の前にオーバーロードの解決も行われます。
したがって、最初に適切なオーバーロードが選択され(テンプレート)、次にアクセス制御が発生し、コンパイラエラーが発生します。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加