Я не уверен, что понимаю вопрос, но в любом случае я пытался смоделировать специализацию шаблона псевдонима.
Я предполагаю, что идея состоит в том, чтобы ограничить шаблон псевдонима определенным типом (сопоставленным с шаблоном);что-то, что мы использовали для такого рода кода:
template<class Vector> struct old_style;
template<class T> struct old_style<std::vector<T> >{
typedef typename std::vector<T>::value_type type;
};
(это всего лишь пример, есть другой способ извлечь value_type
из общего std::vector
).
Теперь к псевдонимам:
template<class Vector> using new_style = typename Vector::value_type;
Это делает ту же самую работу, но это не заменяет old_stype<...>::type
, так как это не столь ограничительно.Первая попытка иметь идеальную замену псевдонима - это гипотетический код:
//template<class Vector> using new_style2; // error already here
//template<class T> using new_style2<std::vector<T> > = typename Vector::value_type;
К сожалению, он не компилируется (теоретически по номинальным причинам, указанным в других ответах и стандарте, на практике, я думаю, что тамнет фундаментальной причины для этого ограничения).К счастью, можно вернуться к старомодному способу struct::type
сделать это, используя только новую функцию шаблона псевдонимов для пересылки работы,
template<class Vector> struct new_style2_aux;
template<class T> struct new_style2_aux<std::vector<T> >{
typedef typename std::vector<T>::value_type type;
};
template<class Vector> using new_style2 = typename new_style2_aux<Vector>::type;
. Можно сделать это автоматически с define
.
#define SPECIALIZED_ALIAS_TEMPLATE(NamE, Pattern_arG, PatterN_expR, DefinitioN) \
template<class> struct NamE ## _aux; \
template<Pattern_arG> struct NamE ## _aux<PatterN_expR>{ \
typedef DefinitioN type; \
}; \
template<class NamE ## _dummy> using NamE = typename NamE ## _aux< NamE ## _dummy >::type;
Что может использоваться как:
SPECIALIZED_ALIAS_TEMPLATE(new_style3, class T, std::vector<T>, typename std::vector<T>::value_type);
Если нужно произвольное количество специализаций (или не локально в коде), нужно использовать более сложный define
в двухчасти, одна для объявления и одна для специализации (как и должно быть):
#define DECLARE_ALIAS_TEMPLATE(NamE)\
template<class> struct NamE ## _aux;\
template<class NamE ## _dummy> using NamE = typename NamE ## _aux< NamE ## _dummy >::type;
#define SPECIALIZE_ALIAS_TEMPLATE(NamE, Pattern_arG, PatterN_expR, DefinitioN)\
template<Pattern_arG> struct NamE ## _aux<PatterN_expR>{ \
typedef DefinitioN type; \
};
Используется следующим образом:
DECLARE_ALIAS_TEMPLATE(new_style4);
SPECIALIZE_ALIAS_TEMPLATE(new_style4, class T, std::vector<T>, typename std::vector<T>::value_type);
SPECIALIZE_ALIAS_TEMPLATE(new_style4, class T, std::set<T>, typename std::set<T>::value_type);
Весь код выше можно скопировать и вставить для проверки:
#include<vector>
#include<map>
// ... paste code above //
int main(){
old_style<std::vector<double> >::type a; // is a double
// old_style<std::set<double> >::type a; // error (should work only for std::vector)
new_style2<std::vector<double> > b; // is double
// new_style2<std::set<double> > c; // error (should work only for std::vector)
new_style3<std::vector<double> > d; // is double
// new_style3<std::set<double> > d; // error (should work only for std::vector)
new_style4<std::vector<double> > e; // is double
new_style4<std::set<double> > f; // is double, this is another specialization
return 0;
}
Извините, если это не то, что вы ищете.Я полагаю, что его можно использовать с шаблонами с переменными значениями и с дополнительными аргументами (в специализации), но не проверял его.
Улучшения приветствуются.