То, на что вы надеетесь, невозможно. И вот почему:
one<instantiated>{};
two<sample_templated>{};
one
«использует» больше, чем two
: это относится к instantiated
, которому sample_templated
соответствует double
. two
, с другой стороны, только «использует» sample_templated
.
Когда вы думаете о шаблонах как о функциях над типами, это становится еще понятнее: two
- это функция, которая принимает функцию (на уровне типа) для создания некоторого типа. one
- это функция, которая принимает тип для создания некоторого типа:
one :: T -> one<T>
two :: (T -> U) -> two<(T -> U)>
Иными словами, параметр one
имеет другой "вид" ("тип типа"), чем параметр two
.
Что вы можете сделать:
Можно указать специализацию one
, которая принимает параметр шаблона шаблона («функция уровня типа») и параметр шаблона для этого:
template<template<typename...> typename TT, typename T>
struct one<TT<T>> { /* ... */ }; // this basically "calls" TT
Вы можете превратить two
во что-то, что может принимать и то и другое, хотя и с "фиктивным" параметром шаблона шаблона:
template<template<typename...> typename TT, typename... Ts>
struct two { /* */ };
template<typename...>
struct Void;
template<typename T>
struct two<Void<>, T> { /* Use T like in one */ };
// or derive from one<T>
Возможно, есть и другие подходы, но они будут зависеть от вашего конкретного варианта использования.