template<class T> class A { // primary template int x; }; template<class T> class A<T*> { // partial specialization long x; }; template<template<class U> class V> class C { V<int> y; V<int*> z; }; C<A> c; // V<int> within C<A> uses the primary template, so c.y.x has type int // V<int*> within C<A> uses the partial specialization, so c.z.x has type long— end example
template<class T> class A { /* ... */ }; template<class T, class U = T> class B { /* ... */ }; template<class ... Types> class C { /* ... */ }; template<auto n> class D { /* ... */ }; template<template<class> class P> class X { /* ... */ }; template<template<class ...> class Q> class Y { /* ... */ }; template<template<int> class R> class Z { /* ... */ }; X<A> xa; // OK X<B> xb; // OK X<C> xc; // OK Y<A> ya; // OK Y<B> yb; // OK Y<C> yc; // OK Z<D> zd; // OK— end example
template <class T> struct eval; template <template <class, class...> class TT, class T1, class... Rest> struct eval<TT<T1, Rest...>> { }; template <class T1> struct A; template <class T1, class T2> struct B; template <int N> struct C; template <class T1, int N> struct D; template <class T1, class T2, int N = 17> struct E; eval<A<int>> eA; // OK: matches partial specialization of eval eval<B<int, float>> eB; // OK: matches partial specialization of eval eval<C<17>> eC; // error: C does not match TT in partial specialization eval<D<int, 17>> eD; // error: D does not match TT in partial specialization eval<E<int, float>> eE; // error: E does not match TT in partial specialization— end example
template<typename T> concept C = requires (T t) { t.f(); }; template<typename T> concept D = C<T> && requires (T t) { t.g(); }; template<template<C> class P> struct S { }; template<C> struct X { }; template<D> struct Y { }; template<typename T> struct Z { }; S<X> s1; // OK, X and P have equivalent constraints S<Y> s2; // error: P is not at least as specialized as Y S<Z> s3; // OK, P is at least as specialized as Z— end example