I see two possible answers without knowing more about the context.
template<typename T> class C; template<template<typename> typename TT, typename T> class C<TT<T>> { ... static_assert(std::is_same<TT<T>, Accepted<T>>::value, "The given type is not an instantiation of Accepted!"); ... }
This is only so helpful - what is so special about Accepted? You may have a second template, e.g. SortedAccepted<T>, that meets the same requirements, but you've set out to constrain the template argument to Accepted<T>.
One option is to design Accepted as a contract so that derivations from it must satisfy the same constraints as Accepted itself:
template<template<typename> typename TT, typename T> class C { ... static_assert(std::is_base_of<Accepted<T>, TT<T>>::value, "The given type is not a derivation of Accepted!"); ... };
This follows from the design principle that Accepted should be extended, but not modified, by its derivations. From the previous example, maybe Accepted is required to have an idempotent 'sort' method -- accepted.sort().sort() == accepted.sort() -- whereas SortedAccepted implicitly retains this property, but additionally provides sorted_accepted.sort() == sorted_accepted. You have nothing to lose in allowing a SortedAccepted wherever you expect an Accepted, but plenty to gain!
If I understood your problem correctly, you might be interested in Traits and Concepts.
Type traits as seen in <type_traits> and Boost's extensions are reified contracts, providing compile-time guarantees about collections sharing traits, expressions of these, and so on. For example, S s; T t; auto u = s + t where std::is_arithmetic<S>::value and std::is_arithmetic<T>::value are true, guarantees that std::is_arithmetic<decltype(u)>::value is true; if either is_floating_point, so is u.
Concepts are the next logical step from type traits: essentially, the reified requirement of traits. (See: 'Concepts Lite')
C<double>?template<typename> class C;and define astemplate<template<typename> typename TT, typename T> struct C<TT<T>> {...}with a static assertion that TT is Accepted, a constraint which you could relax by asserting only the contracts satisfied by (instantiations of) Accepted are satisfied by the given type. I would generally design Accepted to internally require/assert that its contracts are satisfied, and leave C agnostic to the type beyond asserting that an instantiation of Accepted with the given type is well-formed.Cto have aTparameter that will be used to form correspondingAcceptedspecialization instead of taking thatAcceptedspecialization as parameter? SoC<int>will utilizeAccepted<int>automatically.std::is_base_of<Accepted<T>,TT<T>>, assuming extensions of an instantiation satisfy the same constraints as their base (necessarily or voluntarily). It remains to be seen if this is your intention, but as you are, you're not just requiring that the type is derived from Accepted<T>, you're stripping all non-trivial derivations.