質問: ### 前提・実現したいこと テンプレートclass Aのプライベートメンバ関数をテンプレートclass Bから利用したい場合,classAにフレンド宣言をすることで通常は解決できると思います。以下のコードで,enum型を引数にした場合にうまくいきません。対処の方法をご存知の方ご教示いただけますでしょうか。 ### 発生している問題・エラーメッセージ ``` 'funcA' is a private member of 'A' ``` ### 該当のソースコード ``` template class B{ public: enum type{a,b,c}; void funcB(type); }; template class A{ friend void B::funcB(B::type ); static void funcA(){}//この関数を利用したい }; template void B::funcB(type){ A::funcA();///ここで利用したい } int main(){ B b; b.funcB(B::type::a); return 0; } ``` ### 試したこと funcB()として,宣言して定義して引数をなくするとエラーは出ません。 ### 補足情報(FW/ツールのバージョンなど) xcode clang c++17
回答: `typename`が必要です ``` -friend void B::funcB(B::type; +friend void B::funcB(typename B::type); ``` C++ のキーワード: typename **用途** * テンプレート宣言において、 型テンプレート引数およびテンプレートテンプレート引数 (C++17以上)を宣言するために class の代替として使用することができます。 * テンプレートの宣言または定義の中で、依存修飾名が型であることを宣言するために使用することができます。 * テンプレートの宣言または定義の中で、 (C++11未満)非依存修飾型名の前で typename を使用することができます。 この場合、効果はありません。 * 要件の中で型要件に対して (C++20以上) すみません、上記はg++でのコンパイルが通らない理由でした。 g++では`typename`が無いと`error: 'B::type' is not a type`とエラーになります。 clangのバグのような気がしますが、 以下のようにするとclang、g++ともにコンパイルが通りました。 ``` template> class A { friend void ClassB::funcB(typename ClassB::type); static void funcA() {} }; ``` コメント頂きましたが、以下のようにしてもコンパイルが通りますね。 ``` template class A { using ClassB = B; friend void ClassB::funcB(typename ClassB::type); static void funcA() {} }; ```