非类型模板参数有点像红头发的继子。
不存在“任何模板参数匹配,无论类型与否”。
如果可以修改F
,您可以通过将常量包装在精简类型中来使其更加统一。所以:
template<typename T, class R>
struct F;
template<typename T, std::size_t R>
struct F<T, std::integral_constant<std::size_t, R>> {};
现在元程序就像is
可以统一写为:
template<template<class...>class Template, class T>
struct is_instantiation : std::false_type {};
template<template<class...>class Template, class... Ts>
struct is_instantiation<Template, Template<Ts...>> : std::true_type {};
匹配一切。
如果你的控制能力较差F
,您可以使用您的方法,或者编写元程序来提升template
和一个例子template
变成带有类型包装器的东西。
struct meta_F {
template<class T, std::size_t R>using raw_apply=F<T,R>;
template<class T, class R>using apply=raw_apply<T,R::value_type>;
};
template<class meta_Template, class... Args>
struct type_lifted_template {};
template<class T, std::size_t R>
struct type_lifted_template< meta_F, T, std::integral_constant<std::size_t, R> > {
using result = meta_F::template raw_apply<T, R>;
};
template<class T, std::size_t R>
auto type_lift_instance( F<T,R> )
-> type_lifted_template< meta_F, T, std::integral_constant<std::size_t, R> >;
Now, type_lift_instance
可以专门针对多种类型,并且有些decltype
魔法可以用来提取type_lifted_template
针对不同类型进行专业化。
所有这一切都非常粗糙。如果您要在模板上进行大量元编程,那么您最好只让模板采用统一的类型参数,而不是乱搞这些东西。
template<class meta_F, class C>
struct meta_template_is_lifted : std::false_type {};
template<class meta_F, class...Ts>
struct meta_template_is_lifted<meta_F, type_lifted_template< meta_F, Ts... >> : std::true_type {};
template<class meta_F, class C>
struct meta_template_is : meta_template_is_lifted< meta_F, decltype(type_lift_instance( std::declval<C>() ) ) > {};
这并没有减少多少打字,但是元化仍在远离is
代码(或其他类似代码)。
我可能错误地使用了“lift”。