Следующая программа работает нормально:
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 были явно объявлены во время компиляции и чтобы были разрешены только те специализации, которые имеют смысл для приложения.
Но, как видно из приведенного выше кода, мои последующие разработчики (когда-нибудь!) Могут создавать синтаксически правильные шаблоны, которые не имеют смысла семантически. В частности, приложение знает только, как использовать типы, у которых типы классов и функций равны. Остальное бессмысленно.
Это похоже на случай одной из новых возможностей C ++ 17 +, таких как SFINAE, Ограничения или Концепции. Хотя я читаю об этом, у меня еще нет решения, чтобы сделать такой выбор. В cppreference в разделе «Альтернативы» они предлагают концепции вместо SFINAE, если компилятор поддерживает эту возможность (я использую VS2015).
Что было бы хорошим способом ограничить typename J таким же, как typename U?
typename = std::enable_if_t<std::is_same<U,J>{}>
в списке параметров шаблона должно быть достаточно - person Piotr Skotnicki   schedule 24.05.2016A< D, B< D > > a1;
иA< E, C< E > > a2;
. Использованной конструкцией были «шаблоны шаблонов», на которые указал @skypjack в ссылке. - person rtischer8277   schedule 01.06.2016