为具有常量值的任何模板化类型键入trait

时间:2016-05-06 16:49:59

标签: c++ templates c++11 typetraits

我目前正在为任何具有模板的类型制作一个需要特定实现的代码,所以我正在尝试编写一个对任何模板化类型都适用的类型特征。

现在,我有了这个:

template<class T> 
struct TIsTemplated { enum { Value = 0 }; };

template<template<typename, typename...> class T, typename First, typename... Values> 
struct TIsTemplated<T<First, Values...>> { enum { Value = 1 }; };

这适用于模板类型,如

template<typename T>
struct X { };

但是只要存在具有常量值的类型,它就会失败:

template<typename T, int i = 10>
struct Y {};

我发现我可以做出类似的类型:

template<int A, template<typename, int> class T, typename First> 
struct TIsTemplated<T<First,A>> { enum { Value = 1 }; };

但是,这只有在我事先知道我的类型需要int时才有效。我试图概括一下:

template<typename C>
template<C A, template<typename, C> class T, typename First> 
struct TIsTemplated<T<First,A>> { enum { Value = 1 }; };

但即使这个编译正确,TIsTemplated对于Y类型仍然是假的。有没有办法实现这一点,而不必知道常量类型?

1 个答案:

答案 0 :(得分:1)

template<class...>struct types{using type=types;};

是一组类型。

template<class Scalar, class T>
struct is_template_with_scalar : std::false_type {};

template<class Scalar, template<class,Scalar>class Z, class U, Scalar s>
struct is_template_with_scalar<Scalar, Z<U,s>> : std::true_type {};

如果测试为Scalar类型,则T类型与模式template<class, Scalar>匹配。

我们稍微讨论一下:

template<class Scalar>
struct scalar_test {
  template<class T>
  using result=is_template_with_scalar<Scalar, T>;
};

这需要一堆bool类型,并评估它们的逻辑或:

template<class...Ts>
struct or_types : std::false_type {};

template<class T0, class...Ts>
struct or_types<T0, Ts...> : std::integral_constant<bool, T0{} || or_types<Ts...>{} >
{};

passes_any获取类型列表,以及采用类型的元测试。它会生成一个测试,指出是否通过了任何测试:

template<class List, template<class>class Test>
struct passes_any {};

template<class...Ts, template<class>class Test>
struct passes_any<types<Ts...>, Test> {
  template<class U>
  using result=or_types< typename Test<Ts>::template result<U>... >;
};

现在,我们从:

开始
using scalars_supported = types<int, char, std::size_t, unsigned>; // etc

我们接受了测试:

template<class T>
using is_scalar_template = 
  typename passes_any<scalars_supported,scalar_test>::template result<T>;
给定类型T

如果它是<class, Scalar>列表中任何Scalar模式为scalars_supported的模板实例,则属于真实类型。

live example