C++14 SFINAE 容器类value_type类型提升

2018-06-17 23:21:38来源:未知 阅读 ()

新老客户大回馈,云服务器低至5折

C++14 SFINAE 容器类value_type类型提升

原问题:

已知容器类模板Container及其value_type类型,返回容器类类型Container2,将原value_type按如下规则提升:

  • boolshort intintlong intlong long int,提升为long long int
  • floatdoublelong double,提升为long double
  • default,保持value_type不变

正文: 

根据原问题易得如下结构:

template <???>
??? TypePromotion ???;

template <class T>
using Promotion = ??? TypePromotion ???;

template <template <class> class Container, class T>
struct ContainerPromotion {
  using Type = Container<Promotion<T> >;
};

注解:

TypePromotion为一个待实现的type_traits设施,负责按照规则提升给定类型。

PromotionTypePromotion的对外接口。

ContainerPromotion通过Promotion来定义提升后的容器类类型。

其中TypePromotion需要找出给定类型所属的集合,并定义提升后类型。

如何判断给定类型T是否属于某个类型的集合?

将类型集合作为模板类型参数包,递归展开该类型包。在递归的每一层判断目标类型T与当前类型U是否相同,递归返回判断结果的累计或。

template <class T>
constexpr bool Any() {
  return false;
}

template <class T, class U, class... Types>
constexpr bool Any() {
  return std::is_same<T, U>::value || Any<T, Types...>();
}

如何根据判断结果得到提升后的类型?

std::enable_if_t来启用特定的模板,并通过该模板定义提升后的类型。对于default情况,可以类型集合的补集来实现或降低其重载决策等级。

这里采用函数模板来实现(由于Promotion系列函数模板只出现在decltype表达式中,故不需要定义):

// integer type
template <class T>
std::enable_if_t<Any<T, bool, short, int, long int, long long int>(),
long long int> Promotion(int);

// float type
template <class T>
std::enable_if_t<Any<T, float, double, long double>(),
long double> Promotion(int);

// default
template <class T>
T Promotion(...);

// sugar
template <class T>
using type_promotion_t = decltype(Promotion<T>(0));

完整代码(含测试样例): 

 1 #include <type_traits>
 2 
 3 template <class T>
 4 constexpr bool Any() {
 5   return false;
 6 }
 7 
 8 template <class T, class U, class... Types>
 9 constexpr bool Any() {
10   return std::is_same<T, U>::value || Any<T, Types...>();
11 }
12 
13 // integer type
14 template <class T>
15 std::enable_if_t<Any<T, bool, short, int, long int, long long int>(),
16 long long int> Promotion(int);
17 
18 // float type
19 template <class T>
20 std::enable_if_t<Any<T, float, double, long double>(),
21 long double> Promotion(int);
22 
23 // default
24 template <class T>
25 T Promotion(...);
26 
27 // sugar
28 template <class T>
29 using type_promotion_t = decltype(Promotion<T>(0));
30 
31 template <template <class> class Container, class T>
32 struct ContainerPromotion {
33   using Type = Container<type_promotion_t<T> >;
34 };
35 
36 // Container class template for testing
37 template <class T>
38 class Vector {};
39 
40 int main() {
41   using Type1 = typename ContainerPromotion<Vector, int *>::Type;
42   static_assert(std::is_same<Type1, Vector<int *> >::value, "");
43   
44   using Type2 = typename ContainerPromotion<Vector, short>::Type;
45   static_assert(std::is_same<Type2, Vector<long long int> >::value, "");
46   
47   using Type3 = typename ContainerPromotion<Vector, float>::Type;
48   static_assert(std::is_same<Type3, Vector<long double> >::value, "");
49   
50   return 0;
51 }

FAQ:

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:c++之五谷杂粮---1

下一篇:bzoj1061 [ NOI2008 ] --线性规划