C++ では、テンプレート クラスのインスタンスではなく、テンプレート クラスを参照するテンプレート引数を使用できます。たとえば、fun
以下の関数。
同時に、クラス定義内でテンプレート引数を省略できる機能があります。たとえば、 の定義では、 を含意するtemplate<class T> class A
と言うことができます。A
A<T>
両方のルールが潜在的にあいまいさを生み出す可能性があるケースを見つけました。さらに、あいまいさを解決することはできません。これは MWE であり、 の定義では、としてではなくテンプレート クラスとしてtemplate<class T> class B
参照する必要があります。B
B<T>
template <template<class> class Y, class T>
auto fun(){return Y<T>{};} // fun can be used with a *template* class
template<class T>
struct A{
friend void f(A a){} //A here is implicitly A<T>, ok
};
template<class T>
struct B{
friend void g(B b){
fun<A, void>(); // here A is a template class, ok
fun<B, void>(); // error: no matching function for call to 'fun' because the compiler sees B<T>, not B
} //A here is implicitly A<T>,
};
int main(){
A<void> a{};
B<void> b{};
g(b);
}
(関数g
はクラス内で定義したいフレンド関数であるため、これを行う必要があります。)
Clang 3.5 では上記のエラーが発生しますが、GCC 4.9.2 では問題ありません。最悪の部分は、追加の仕様を作成してあいまいさを解決できないことです。
たとえば、私は試しました:
fun<struct B, void>();
fun<template<class> struct B, void>();
それでも同じエラーが発生します。
テンプレートクラスでB
はないclang(または問題のあるコンパイラ)に伝える方法はありますか?B<T>
B
(例を簡略化するためにいくつかの C++11 構文を使用しましたが、問題は C++98 にも当てはまります。正しい命名規則を使用していない場合は、修正するか、お知らせください。)