C++14 SFINAE 容器类value_type类型提升
原问题:
已知容器类模板Container及其value_type类型,返回容器类类型Container2,将原value_type按如下规则提升:
- bool,short int,int,long int,long long int,提升为long long int
- float,double,long 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设施,负责按照规则提升给定类型。
Promotion为TypePromotion的对外接口。
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:
-
原文链接: https://www.cnblogs.com/activa/p/6361465.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/248642
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!