template<class T1, class T2, int I> class A { }; // #1 template<class T, int I> class A<T, T*, I> { }; // #2 template<class T1, class T2, int I> class A<T1*, T2, I> { }; // #3 template<class T> class A<int, T*, 5> { }; // #4 template<class T1, class T2, int I> class A<T1, T2*, I> { }; // #5 A<int, int, 1> a1; // uses #1 A<int, int*, 1> a2; // uses #2, T is int, I is 1 A<int, char*, 5> a3; // uses #4, T is char A<int, char*, 1> a4; // uses #5, T1 is int, T2 is char, I is 1 A<int*, int*, 2> a5; // ambiguous: matches #3 and #5— end example
template<typename T> concept C = requires (T t) { t.f(); }; template<typename T> struct S { }; // #1 template<C T> struct S<T> { }; // #2 struct Arg { void f(); }; S<int> s1; // uses #1; the constraints of #2 are not satisfied S<Arg> s2; // uses #2; both constraints are satisfied but #2 is more specialized— end example
template <int I, int J> struct A {}; template <int I> struct A<I+5, I*2> {}; // error template <int I> struct A<I, I> {}; // OK template <int I, int J, int K> struct B {}; template <int I> struct B<I, I*2, 2> {}; // OK— end example