如何测试type是否是非类型参数模板的特化?

Bap*_*cht 8 c++ templates c++11 c++14

我想知道是否有任何解决方案可以找到一个类型是否是一个模板的特化,它采用非类型参数而不指定每个类型?

例如,如果有这样的类:

template<typename T, std::size_t R>
struct F {}
Run Code Online (Sandbox Code Playgroud)

现在,我正在使用一个非常专业的特征:

template<template<typename, std::size_t> class TT, typename T>
struct is_2 : std::false_type { };

template<template<typename, std::size_t> class TT, typename V1, std::size_t R>
struct is_2<TT, TT<V1, R>> : std::true_type { };
Run Code Online (Sandbox Code Playgroud)

并使用像is_2<F, T>::value.但是,这是不实际的,因为如果添加另一个模板参数,则必须编辑特征.此外,如果您有多个此类模板,则需要为每个模板编写特征.

有没有办法让事情变得更实用?我可以使用C++ 14.我并不是说使用宏来减少代码量.

Yak*_*ont 8

非类型模板参数有点像红头的继子.

没有"任何模板参数匹配,类型与否".

如果可以修改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>> {};
Run Code Online (Sandbox Code Playgroud)

现在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 {};
Run Code Online (Sandbox Code Playgroud)

匹配一切.

如果你对控制权的控制较少F,你可以使用你的方法,或者编写将程序包template和a 的实例同时提升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> >;
Run Code Online (Sandbox Code Playgroud)

现在,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>() ) ) > {};
Run Code Online (Sandbox Code Playgroud)

这并不是打字少,但是元化远离is代码(或其他类似的代码).

我可能错误地使用"升降机".