次のプログラムは正常に実行されます。
struct M; // forward declare so compiler will recognize this type
struct N;
template< typename J > struct B { template< typename U > void Func1(); };
template<> template<> void B< M >::Func1< M >() {}
template<> template<> void B< N >::Func1< N >() {}
template<> template<> void B< M >::Func1< N >() {} // illegal specialization for this app
template< typename J > struct C { template< typename U > void Func2(); };
template<> template<> void C< M >::Func2< M >() {}
template<> template<> void C< N >::Func2< N >() {}
template< typename G > struct H { G g; };
int main()
{
H< B< M > > hbm;
hbm.g.Func1< M >(); // ok
hbm.g.Func1< N >(); // compiles and runs, but uses a semantically illegal specialization for this app
H< B< N > > hbn;
hbn.g.Func1< N >(); // ok
H< C< M > > hcm;
hcm.g.Func2< M >(); // ok
H< C< N > > hcn;
hcn.g.Func2< N >(); // ok
return 0;
}
構造体 B と C をコンパイル時に明示的に宣言し、アプリにとって意味のある特殊化のみを許可することが重要です。
しかし、上記のコードに見られるように、下流の開発者 (いつか!) が、意味的に意味をなさない構文的に正しいパターンを作成できる可能性があります。具体的には、アプリは、クラスと関数の型が等しい型の使用方法しか認識していません。残りは無意味です。
これは、SFINAE、Constraints、Concepts などの新しい C++17+ 機能の 1 つのケースのようです。私はこれらについて読んでいますが、その選択をする判断はまだありません. Alternatives の下の cppreference では、コンパイラが機能している場合 (私は VS2015 を使用しています)、SFINAE の代わりに Concepts を提案しています。
型名 J が型名 U と同じになるように制約するにはどうすればよいでしょうか?