将各种计算从运行期提前至编译期,以达到提升运行时性能的目的,即是通过增加程序编译时间,来提升程序运行效率的编程手法。元编程中会使用到“递归”技术。
boost库中,MPL(meta-programming library)库,用于辅助模板元编程,《c++模板元编程》有详细介绍。
能在编译期间,被调用和执行的函数(编译期间就能得到结果)。
所谓元编程,就是书写和利用这些元函数进行编程。
举例:c++11 引入的 constexpr 关键字(c++17中使constexpr自带inline属性):用于在编译时求值。
#include
using namespace std;
// 元函数(数值元函数):
constexpr int func(int val)
{
return val * 2;
}
int main()
{
// 因func()函数和val变量前均加了constexpr关键字,故val在编译期间,就能进行计算
constexpr int val = func(12);
static_assert(val == 24, "std error");
// static_assert:用于在编译时进行断言检查
// 元函数运行期间,也能调用
int x = 10;
cout << func(x) << endl;
return 0;
}
#include
using namespace std;
/* 要求:实现编译期间,阶乘的计算 */
// 泛化版本:
template <int val>
class Factorial
{
public:
enum
{
value = val * Factorial<val - 1>::value
};
};
// 特化版本:用于递归结束的出口
template <>
class Factorial<1>
{
public:
enum
{
value = 1
};
};
int main()
{
cout << Factorial<5>::value << endl;
return 0;
}
#include
using namespace std;
/* 要求:函数内部递归,实现编译期间,阶乘的计算 */
namespace _nmsp_recursive {
constexpr int Factorial(int val)
{
return val <= 1 ? 1 : (Factorial(val - 1) * val);
}
}
/* 要求:函数内部for循环,实现编译期间,阶乘的计算 */
namespace _nmsp_for {
constexpr int Factorial(int val)
{
int result = 1;
for (; val > 0; --val)
{
result *= val;
}
return result;
}
}
int main()
{
constexpr int val = Factorial(5);
static_assert(val == 120, "std error");
cout << val << endl;
return 0;
}
#include
using namespace std;
/* 要求:实现编译期间,阶乘的计算 */
namespace _nmsp_factorial {
// 泛化版本的变量模板
template <int val>
constexpr int result = val * result<val - 1>;
// 特化版本的变量模板
template <>
constexpr int result<1> = 1;
void test()
{
constexpr int val = result<5>;
static_assert(val == 120, "std error");
cout << val << endl;
}
}
/* 要求:实现编译期间,求和运算 */
namespace _nmsp_sum {
// 泛化版本的变量模板:只有参数为0个时,才会调用
template <int... Args>
constexpr int sum = 0;
// 特化版本的变量模板
template <int val, int... others>
constexpr int sum<val, others...> = val + sum<others...>;
void test()
{
constexpr int val = sum<1,2,3,4,5>;
static_assert(val == 15, "std error");
cout << val << endl;
}
}
std::remove_all_extents
类模板,实现的元编程就是靠“递归模板实例化”来驱动的。
fixed trait
类模板),就可以成为类型元函数。#include
using namespace std;
template <typename T>
class AddPoint
{
public:
using type = T*;
};
int main()
{
AddPoint<const char>::type str = "hello";
cout << typeid(str).name() << endl;
return 0;
}
#include
using namespace std;
template <typename T>
using AddPoint = T*;
int main()
{
AddPoint<const char> str = "hello";
cout << typeid(str).name() << endl;
return 0;
}
可宽泛的认为:只要用于元编程中,且编译器期间能够被调用,都可以视为元函数(不避局限于类型元函数、数值元函数)。
#include
using namespace std;
/* 实现两个一维数组的点积运算:*/
namespace _OrdinaryOperation
{
// 函数模板:
template <typename T, size_t n>
T DotProduct(const T* arr1, const T* arr2)
{
T result = T{}; // 零初始化
for (int i = 0; i < n; ++i)
{
result += ((*(arr1++)) * (*(arr2++)));
}
return result;
}
}
namespace _Mixed_MetaProgram
{
// 泛化版本:
template <typename T, size_t n>
class DotProduct
{
public:
static T result(const T* arr1, const T* arr2)
{
return (*arr1) * (*arr2) + DotProduct<T, n - 1>::result(arr1 + 1, arr2 + 1);
}
};
// 特化版本:用于递归的出口
template <typename T>
class DotProduct<T, 0>
{
public:
static T result(const T* arr1, const T* arr2)
{
return T{}; // 零初始化
}
};
}
int main()
{
int arr1[3] = {1,2,3};
int arr2[3] = {4,5,6};
cout << _OrdinaryOperation::DotProduct<int, 3>(arr1, arr2) << endl;
cout << _Mixed_MetaProgram::DotProduct<int, 3>::result(arr1, arr2) << endl;
// 编译器会根据这行代码生成新的代码,如下:
// cout << (*arr1) * (*arr2) + (*(arr1 + 1)) * (*(arr2 + 1)) + (*(arr1 + 2)) * (*(arr2 + 2)) << endl;
return 0;
}
注意:使用元编程计算点积时,当一维数组过长,编译器会智能的通过一些函数调用避免产生过分冗长的代码。但该过程会导致可执行程序的尺寸变大,即产生了代码膨胀。
前期阶段:c++编译器直接对c++源码(元编程代码)进行解释执行,会产生一系列c++代码,故元编程才会被看作“c++代码生成器”。
后期阶段:针对前期产生的代码进行编译、链接,最终生成可执行文件。
#include
using namespace std;
namespace _nmsp_1
{
// 泛化版本:
template <int x, int y>
class InstantiationObserve
{
public:
static const int value = (x > y) ? InstantiationObserve<x - 1, y>::value : InstantiationObserve<x, x>::value;
};
// 特化版本:
template <int x>
class InstantiationObserve<x, x>
{
public:
static const int value = x;
};
}
namespace _nmsp_2
{
// 泛化版本:
template <int x, int y>
class InstantiationObserve
{
public:
using type = typename std::conditional<(x > y), InstantiationObserve<x - 1, y>, InstantiationObserve<x, x>>::type;
static const int value = type::value;
};
// 特化版本:
template <int x>
class InstantiationObserve<x, x>
{
public:
static const int value = x;
};
}
int main()
{
// 元编程中,如果使用了条件运算符,则可能将所涉及到的类都实例化出来
cout << _nmsp_1::InstantiationObserve<5,3>::value << endl;
// 元编程中,如果使用std::conditional,则可能避免将无用的类实例化出来
cout << _nmsp_2::InstantiationObserve<5,3>::value << endl;
// 元编程中,如果使用了enum{}枚举类型,则可能代码在编译器进一步被简化
return 0;
}
c++17开始,constexpr自带inline属性;
使用枚举类型与inline静态成员变量(c++11引入)相同,都不存在额外占用内存空间的问题 。
#include
using namespace std;
struct A
{
enum { value1 = 12 };
static inline const int value2 = 12;
};
一个类型容器,对类型提供了一系列操作(将类型看作数据来操作)。本质:一个类模板,用来表示一个列表,其中存放的是一堆类型。
#include
using namespace std;
namespace _nmsp
{
/* ..... NullTypeList:表示空typelist列表 ..... */
class NullTypeList {};
/* ..... typelist类模板:实现列表头类型Head + Tail其余类类型 ..... */
template <typename T, typename U = NullTypeList>
class typelist
{
public:
using Head = T;
using Tail = U;
};
/* ..... is_empty类模板:判断typelist中类类型是否为空 ..... */
// 泛化版本:
template <typename TypeList>
class is_empty
{
public:
static const bool value = false;
};
// 特化版本:
template <>
class is_empty<NullTypeList>
{
public:
static const bool value = true;
};
/* ..... size类模板:获取typelist中类类型的个数 ..... */
// 泛化版本:只声明不定义,用来引出特化版本
template <typename TypeList>
class size;
// 特化版本2:用来递归结束的出口
template <>
class size<NullTypeList>
{
public:
static const size_t count = 0;
};
// 特化版本2:用来递归实例化展开
template <typename T, typename U>
class size<typelist<T, U>>
{
public:
static const size_t count = size<U>::count + 1;
};
/* ..... front类模板:获取typelist中,第一个类类型 ..... */
template <typename TypeList>
class front
{
public:
using type = typename TypeList::Head;
};
/* ..... pop_front类模板:从typelist中,移除第一个类类型 ..... */
template <typename TypeList>
class pop_front
{
public:
using type = typename TypeList::Tail;
};
/* ..... push_front类模板:给typelist头插一个类类型 ..... */
template <typename TypeList, typename insertType>
class push_front
{
public:
using type = typelist<insertType, TypeList>;
};
/* ..... find类模板_1:在typelist中,根据索引查找类类型 ..... */
/* 这种写法:容易出现越界问题,导致编译错误 */
// 泛化版本:用作递归实例化
template <typename TypeList, size_t index>
class find_1 : public find_1<typename pop_front<TypeList>::type, index - 1>
{};
// 特化版本:作为递归结束的出口
template <typename TypeList>
class find_1<TypeList, 0> : public front<TypeList>
{};
/* ..... find类模板_2:在typelist中,根据索引查找类类型 ..... */
/* 这种写法:容易出现越界问题,导致编译错误 */
// 泛化版本:只声明不定义,用来引出特化版本
template <typename TypeList, size_t index>
class find_2;
//特化版本1:递归结束的出口
template <typename Head, typename Tail>
class find_2<typelist<Head, Tail>, 0>
{
public:
using type = Head;
};
//特化版本:用于递归实例化的过程
template <typename Head, typename Tail, size_t index>
class find_2<typelist<Head, Tail>, index>
{
public:
using type = typename find_2<Tail, index - 1>::type;
};
/* ..... find类模板_3:在typelist中,根据索引查找类类型 ..... */
/* 这种写法:出现越界问题时,返回空列表即NullTypeList */
// 泛化版本:当出现越界问题时,调用该泛化版本
template <typename TypeList, size_t index, typename DefaultType = NullTypeList>
class find_3
{
public:
using type = DefaultType;
};
//特化版本1:递归结束的出口
template <typename Head, typename Tail, typename DefaultType>
class find_3<typelist<Head, Tail>, 0, DefaultType>
{
public:
using type = Head;
};
//特化版本:用于递归实例化的过程
template <typename Head, typename Tail, size_t index, typename DefaultType>
class find_3<typelist<Head, Tail>, index, DefaultType>
{
public:
using type = typename find_3<Tail, index - 1, DefaultType>::type;
};
}
#define TypeList1(T1) _nmsp::typelist<T1, _nmsp::NullTypeList>
#define TypeList2(T1, T2) _nmsp::typelist<T1, TypeList1(T2)>
#define TypeList3(T1, T2, T3) _nmsp::typelist<T1, TypeList2(T2, T3)>
#define TypeList4(T1, T2, T3, T4) _nmsp::typelist<T1, TypeList3(T2, T3, T4)>;
int main()
{
using typelist4 = TypeList4(int, bool, float, double);
cout << _nmsp::is_empty<typelist4>::value << endl;
cout << _nmsp::size<typelist4>::count << endl;
cout << typeid(_nmsp::front<typelist4>::type).name() << endl;
cout << "*************************************" << endl;
using typelist3 = typename _nmsp::pop_front<typelist4>::type;
cout << typeid(_nmsp::front<typelist3>::type).name() << endl;
cout << _nmsp::size<typelist3>::count << endl;
cout << "*************************************" << endl;
using typelist4_ = typename _nmsp::push_front<typelist3, int>::type;
cout << typeid(_nmsp::front<typelist4_>::type).name() << endl;
cout << _nmsp::size<typelist4_>::count << endl;
cout << "*************************************" << endl;
cout << typeid(_nmsp::find_1<typelist4_, 2>::type).name() << endl;
cout << typeid(_nmsp::find_2<typelist4_, 2>::type).name() << endl;
cout << typeid(_nmsp::find_3<typelist4_, 4>::type).name() << endl;
return 0;
}
namespace _nmsp_baseInterface
{
/* ...... typelist类模板:用来接收一堆类类型 ...... */
// 可变参模板参数,用来接收一堆类型,并存放在typelist中
template <typename... T>
class typelist;
/* ...... is_empty类模板:判断typelist中类类型是否为空 ...... */
// 泛化版本:typelist中类类型的个数不为0(即不为空)时,调用泛化版本
template <typename TypeList> // 此时,TypeList中存放了一堆类型
class is_empty
{
public:
static const bool value = false;
//static inline const bool value = false;
// 注意:inline variables are only available with ‘-std=c++17’ or ‘-std=gnu++17’
};
// 特化版本:typelist中类类型的个数为0(即为空)时,调用特化版本
template <>
class is_empty<typelist<>>
{
public:
static const bool value = true;
};
/* ...... size类模板:获得typelist中类类型的个数 ...... */
// 泛化版本:只声明,用来引出特化版本
template <typename TypeList>
class size;
// 特化版本:用来获取typelist中类类型的个数
template <typename... TypeArgs>
class size<typelist<TypeArgs...>>
{
public:
static const size_t count = sizeof...(TypeArgs);
};
/* ...... front类模板:提取typelist中的第一个类型 ...... */
// 泛化版本:只声明,用来引出特化版本
// 注意:只有TypeList中类类型为空时,才会调用泛化版本
template <typename TypeList>
class front;
// 特化版本:用来提取出typelist中的第一个类型
template <typename FirstType, typename... OtherTypes>
class front<typelist<FirstType, OtherTypes...>>
{
public:
using type = FirstType;
};
/* ...... pop_front类模板:移除typelist中的第一个类型 ...... */
// 泛化版本:只声明,用来引出特化版本
// 注意:只有TypeList中类类型为空时,才会调用泛化版本
template <typename TypeList>
class pop_front;
// 特化版本:用来移除typelist中的第一个类型
template <typename FirstType, typename... OtherTypes>
class pop_front<typelist<FirstType, OtherTypes...>>
{
public:
using type = typelist<OtherTypes...>;
};
/* ...... push_front类模板:给typelist头插一个类型 ...... */
// 泛化版本:只声明,用来引出特化版本
template <typename TypeList, typename insertType>
class push_front;
// 特化版本:用来给typelist头插一个类型
template <typename... srcTypes, typename insertType>
class push_front<typelist<srcTypes...>, insertType>
{
public:
using type = typelist<insertType, srcTypes...>;
};
/* ...... push_back类模板:给typelist尾插一个类型 ...... */
// 泛化版本:只声明,用来引出特化版本
template <typename TypeList, typename insertType>
class push_back;
// 特化版本:用来给typelist尾插一个类型
template <typename... srcTypes, typename insertType>
class push_back<typelist<srcTypes...>, insertType>
{
public:
using type = typelist<srcTypes..., insertType>;
};
/* ...... replace_front类模板:替换typelist首个类类型 ...... */
// 泛化版本:只声明,用来引出特化版本
template <typename TypeList, typename replaceType>
class replace_front;
// 特化版本:替换typelist首个类类型
template <typename FirstType, typename... OtherTypes, typename replaceType>
class replace_front<typelist<FirstType, OtherTypes...>, replaceType>
{
public:
using type = typelist<replaceType, OtherTypes...>;
};
void test()
{
using tylist1 = _nmsp_baseInterface::typelist<int, float, double, char, string>;
cout << _nmsp_baseInterface::size<tylist1>::count << endl;
cout << typeid(_nmsp_baseInterface::front<tylist1>::type).name() << endl;
using tylist1_deletefront = _nmsp_baseInterface::pop_front<tylist1>::type;
cout << _nmsp_baseInterface::size<tylist1_deletefront>::count << endl;
cout << typeid(_nmsp_baseInterface::front<tylist1_deletefront>::type).name() << endl;
using tylist1_frontinsert = _nmsp_baseInterface::push_front<tylist1, short>::type;
cout << _nmsp_baseInterface::size<tylist1_frontinsert>::count << endl;
cout << typeid(_nmsp_baseInterface::front<tylist1_frontinsert>::type).name() << endl;
using tylist1_backinsert = _nmsp_baseInterface::push_back<tylist1, size_t>::type;
cout << _nmsp_baseInterface::size<tylist1_backinsert>::count << endl;
using tylist1_replacefront = _nmsp_baseInterface::replace_front<tylist1, size_t>::type;
cout << _nmsp_baseInterface::size<tylist1_replacefront>::count << endl;
cout << typeid(_nmsp_baseInterface::front<tylist1_replacefront>::type).name() << endl;
cout << "..........................................." << endl;
using tylist2 = _nmsp_baseInterface::typelist<>;
cout << _nmsp_baseInterface::size<tylist2>::count << endl;
cout << _nmsp_baseInterface::is_empty<tylist2>::value << endl;
/*
cout << typeid(_nmsp_baseInterface::front::type).name() << endl;
// Error:因_nmsp_baseInterface::front此时调用的是泛化版本的front类模板
//,其内部并未定义type故会报错
using tylist2_delete1 = _nmsp_baseInterface::pop_front::type;
// Error:因_nmsp_baseInterface::pop_front此时调用的是泛化版本的pop_front类模板
//,其内部并未定义type故会报错
*/
}
}
namespace _nmsp_extentInterface
{
/* ...... find类模板:找到typelist中,索引为index的类类型 ...... */
// 泛化版本:实现递归实例化的过程
// 如果index越界,则编译期会报错
template <typename TypeList, size_t index>
class find : public find<typename _nmsp_baseInterface::pop_front<TypeList>::type, index - 1>
{ };
// 特化版本:用来作为递归继承的结束出口
template <typename TypeList>
class find<TypeList, 0> : public _nmsp_baseInterface::front<TypeList>
{ };
void test()
{
using tylist1 = _nmsp_baseInterface::typelist<int, double, float, char, bool>;
cout << typeid(_nmsp_extentInterface::find<tylist1, 0>::type).name() << endl;
// 如果index越界,则编译期会报错
}
}
namespace _nmsp_extentInterface {
/* ...... get_maxsize_type类模板:找到typelist中,sizeof最大的类类型 ...... */
// 泛化版本:实递归实例化的过程
template <typename TypeList>
class get_maxsize_type
{
private:
using firstElementType = typename _nmsp_baseInterface::front<TypeList>::type;
using remainElements = typename _nmsp_baseInterface::pop_front<TypeList>::type;
using first_remainElements_Type = typename get_maxsize_type<remainElements>::type;
public:
using type = typename std::conditional<(sizeof(firstElementType) >= sizeof(first_remainElements_Type)), firstElementType, first_remainElements_Type>::type;
};
// 特化版本:用来作为递归结束的出口
template <>
class get_maxsize_type<_nmsp_baseInterface::typelist<>>
{
public:
using type = char;
};
void test()
{
using tylist1 = _nmsp_baseInterface::typelist<int, double, float, char, bool>;
cout << typeid(_nmsp_extentInterface::get_maxsize_type<tylist1>::type).name() << endl;
}
}
namespace _nmsp_extentInterface
{
/* ...... reverse类模板:将typelist中的类类型按现有顺序反转 ...... */
// 泛化版本:是声明不定义,用来引出特化版本
template <typename TypeList, bool = _nmsp_baseInterface::is_empty<TypeList>::value>
class reverse;
// 特化版本1:
template <typename TypeList>
class reverse<TypeList, false>
{
private:
using firstElementType = typename _nmsp_baseInterface::front<TypeList>::type;
using reversed_results = typename reverse<typename _nmsp_baseInterface::pop_front<TypeList>::type>::type;
public:
using type = typename _nmsp_baseInterface::push_back<reversed_results, firstElementType>::type;
};
// 特化版本2:
template <typename TypeList>
class reverse<TypeList, true>
{
public:
using type = TypeList;
};
void test()
{
using tylist1 = _nmsp_baseInterface::typelist<int, double, float, char, bool>;
using reversed_tylist1 = _nmsp_extentInterface::reverse<tylist1>::type;
cout << typeid(_nmsp_baseInterface::front<reversed_tylist1>::type).name() << endl;
}
}
元组tuple是一个可以装不同类型元素和数组/容器。
#include
#include
using namespace std;
namespace _nmsp_tuple_baseInterface
{
/* .. 该函数模板用来识别类中是否含有tuple_fun()函数,即判断该类是否时tuple类 .. */
template <typename T, typename U = std::void_t<>>
class HasMemTupleFunc : public std::false_type
{ };
// 特化版本:std::declval().tuple_func()可在不构建T类对象的情况下,达到构建了对象的效果
template <typename T>
class HasMemTupleFunc<T, std::void_t<decltype(std::declval<T>().tuple_func())>> : public std::true_type
{ };
/* ......................................... */
// 泛化版本:只声明不定义,用来引出特化版本
template <typename... Types>
class tuple;
// 特化版本1:用来递归实例化的过程
template <typename First, typename... Others>
class tuple<First, Others...>
{
public:
First first;
tuple<Others...> others;
public:
// 默认构造函数:
tuple()
{
cout << "tuple::tuple()" << endl;
}
// 有参构造函数(模板):
// 这里使用“万能引用 + std::forward”,可还原原始传入的实参的左右值属性,即实现“完美转发”
// 通过“完美转发”,可在拷贝过程中,对右值进行移动拷贝,故可提高程序的效率
template <typename _First, typename... _Others
, typename = std::enable_if_t< !HasMemTupleFunc<_First>::value >>
tuple(_First&& _first, _Others&&... _others) : first(std::forward<_First>(_first))
, others(std::forward<_Others>(_others)...)
{
cout << "tuple::tuple(_First&& _first, _Others&&... _others)" << endl;
}
// 拷贝构造函数:
/*
// 如果形参用const修饰,编译器会报错
// 原因:本该在拷贝构造时调用该函数,结果编译器却调用了有参构造函数,导致出现错误
tuple(const tuple& _tuple) : first(_tuple.first), others(_tuple.others)
{
cout << "tuple::tuple(const tuple& _tuple)" << endl;
}
*/
/*
// 解决方法,将形参的const修饰符,拿掉
// 但存在新的问题:无法正常拷贝“常量tuple对象”或“显式转换得到的tuple对象”
tuple(tuple& _tuple) : first(_tuple.first), others(_tuple.others)
{
cout << "tuple::tuple(const tuple& _tuple)" << endl;
}
*/
// 解决方法:
// 1、在tuple类中引入一个tuple类专属的成员函数,用来识别tuple类
// 2、在有参构造函数(模板)的模板参数列表中,加入一个模板参数
// typename = std::enable_if_t::value
// ,表示只有在传入的第一个实参不是tuple类型时,才会调用高函数
tuple(const tuple<First, Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
{
cout << "tuple::tuple(const tuple& _tuple)" << endl;
}
// 拷贝构造函数模板:
// 当调用拷贝构造时,_First参数类型与First不一致时,则会调用“拷贝构造函数模板”
template <typename _First, typename... _Others>
tuple(const tuple<_First, _Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
{
cout << "tuple<_First, _Others...>::tuple(const tuple<_First, _Others...>& _tuple)" << endl;
}
public:
void tuple_func() {}
};
// 特化版本2:作为递归结束的出口
template <>
class tuple<>
{
public:
tuple() { cout << "tuple<>::tuple()" << endl; }
tuple(const tuple<>&) { cout << "tuple<>::tuple(const tuple<>&)" << endl; }
};
/* 通过get函数得到tuple中的第index个元素:*/
// 泛化版本:用于递归实例化展开
template <size_t index>
class GetHelper
{
public:
template <typename First, typename... Others>
static auto getHelper(const tuple<First, Others...>& _tuple)
{
return GetHelper<index - 1>::getHelper(_tuple.others);
}
};
// 特化版本:用于递归结束的出口
template <>
class GetHelper<0>
{
public:
template <typename First, typename... Others>
static auto getHelper(const tuple<First, Others...>& _tuple)
{
return _tuple.first;
}
};
// 函数模板:用于对外调用的接口
template <size_t index, typename... Types>
auto get(const tuple<Types...>& _tuple)
{
return GetHelper<index>::getHelper(_tuple);
}
/* 通过make_tuple函数,可将不同类型的数据打包转化为tuple类型:*/
template <typename... Types>
auto make_tuple(Types&&... args) // 形参是万能引用
{
return tuple<std::decay_t<Types>...>(std::forward<Types>(args)...);
}
// 这里make_tuple的类型推导技术:可根据传入的实参自动推导出元素的类型,并将“退化”后的类型放入tuple中
void test()
{
tuple<int, float, double> mytuple1;
cout << "*********************************************" << endl;
tuple<int, float, double, string> mytuple2(int(1), float(2.1), double(3.5), string("hello"));
cout << "*********************************************" << endl;
tuple<int, float, double, string> mytuple3(mytuple2);
cout << "...当mytuple4==>First==double、mytuple2==>First==int时,类型不一致时,需通过调用“拷贝构造函数模板”完成拷贝 ..." << endl;
tuple<double, float, double, string> mytuple4(mytuple2);
cout << "*********************************************" << endl;
tuple<double> mytuple5(3.5);
cout << "---------------------------------------------" << endl;
// 这里第三个参数的拷贝,调用的是“拷贝构造函数模板”
tuple<int, float, tuple<double>> mytuple6(int(1), float(2.1), mytuple5);
cout << "---------------------------------------------" << endl;
tuple<int, double> mytuple5_(3.5);
tuple<tuple<int, double>> mytuple6_(mytuple5);
// 这里注意:如果嵌套的tuple中,存在两个及以上的类型,则会报错,原因是调用拷贝构造函数模板时
//,First == tuple 与 _First == int,不一致导致的
/* 这里需要进一步有待完善。。。 */
cout << "*********************************************" << endl;
cout << get<0>(mytuple6) << endl;
cout << get<1>(mytuple6) << endl;
cout << get<0>(get<2>(mytuple6)) << endl;
cout << "*********************************************" << endl;
auto mytuple7 = _nmsp_tuple_baseInterface::make_tuple(int(1), float(2.1), double(3.5), string("hello"));
cout << "*********************************************" << endl;
}
}
namespace _nmsp_tuple_extentInterface
{
/* pop_front_type类模板:从tuple中移除第一个“类型” */
// 泛化版本:
template <typename Tuple>
class pop_front_type;
// t特化版本:
template <typename First, typename... Others>
class pop_front_type<_nmsp_tuple_baseInterface::tuple<First, Others...>>
{
public:
using type = _nmsp_tuple_baseInterface::tuple<Others...>;
};
/* push_front函数模板:向tuple的头插一个元素 */
// 普通实现方法:
template <typename... Types, typename insertType>
auto push_front(const _nmsp_tuple_baseInterface::tuple<Types...>& _tuple, const insertType& newElement)
{
return _nmsp_tuple_baseInterface::tuple<insertType, Types...>(newElement, _tuple);
}
// 递归方法:
// 1、递归结束的出口
template <typename insertType>
auto push_front_recursive(const _nmsp_tuple_baseInterface::tuple<>& _tuple, const insertType& newElement)
{
return _nmsp_tuple_baseInterface::tuple<insertType>(newElement);
}
// 2、递归实例化的过程:
template <typename First, typename... Others, typename insertType>
auto push_front_recursive(const _nmsp_tuple_baseInterface::tuple<First, Others...>& _tuple, const insertType& newElement)
{
return _nmsp_tuple_baseInterface::tuple<insertType, First, Others...>(newElement, push_front_recursive(_tuple.others, _tuple.first));
}
/* push_back函数模板:向tuple的头插一个元素 */
/*
//普通实现写法:不支持这种写法
template
auto push_back(const _nmsp_tuple_baseInterface::tuple& _tuple, const insertType& newElement)
{
return _nmsp_tuple_baseInterface::tuple(_tuple, newElement);
}
*/
// 递归方法:
// 1、递归结束的出口
template <typename insertType>
auto push_back(const _nmsp_tuple_baseInterface::tuple<>& _tuple, const insertType& newElement)
{
return _nmsp_tuple_baseInterface::tuple<insertType>(newElement);
}
// 2、递归实例化的过程:
template <typename First, typename... Others, typename insertType>
auto push_back(const _nmsp_tuple_baseInterface::tuple<First, Others...>& _tuple, const insertType& newElement)
{
return _nmsp_tuple_baseInterface::tuple<First, Others..., insertType>(_tuple.first, push_back(_tuple.others, newElement));
}
/* pop_front函数模板:从tuple中移除第一个元素 */
template <typename Tuple>
auto pop_front(const Tuple& _tuple)
{
return _tuple.others;
}
/* reverse函数模板:反转一个tuple中的元素顺序 */
// 递归方法:
// 1、递归结束的出口
auto reverse(const _nmsp_tuple_baseInterface::tuple<>&)
{
return _nmsp_tuple_baseInterface::tuple<>();
}
// 2、递归的过程
template <typename First, typename... Others>
auto reverse(_nmsp_tuple_baseInterface::tuple<First, Others...>& _tuple)
{
return push_back(reverse(_tuple.others), _tuple.first);
}
// 结合IntegerSequence_Reverse,实现reverse:
namespace IntegerSequenceReverse
{
/* 定义 IntegerSequence_pushBack 类模板(泛化和特化版本),用来实现“尾插”的功能: */
template <typename T, size_t newElement>
class IntegerSequence_pushFront; // 因不使用泛化版本,故只声明不定义
template <typename T, size_t... Elements, size_t newElement>
class IntegerSequence_pushFront<std::integer_sequence<T, Elements...>, newElement>
{
public:
using type = std::integer_sequence<T, newElement, Elements...>;
};
/* .................................... */
/* 自定义 Integer_Sequence 类模板(泛化和特化版本),用来实现make_integer_sequence的功能:*/
// 泛化版本:
template <typename T, size_t N>
class Integer_Sequence_Reverse
{
public:
// 依次遍历出N-1、...、3、2、1、0,并逐个通过IntegerSequence_pushBack尾插
using type = typename IntegerSequence_pushFront<typename Integer_Sequence_Reverse<T, N - 1>::type, N - 1>::type;
};
// 特化版本:
template <typename T>
class Integer_Sequence_Reverse<T, 1>
{
public:
using type = std::integer_sequence<T, 0>;
};
/* .................................... */
/* 定义别名模板:*/
template <typename T, size_t N>
using Integer_Sequence_Reverse_T = typename Integer_Sequence_Reverse<T, N>::type;
/* .................................... */
}
template <typename... Types, size_t... integralSequence>
auto reverseHelper(const _nmsp_tuple_baseInterface::tuple<Types...>& _tuple, std::integer_sequence<size_t, integralSequence...>)
{
// 这里将传入的逆序整形序列,作为get中的index,进而实现逆序
return make_tuple(_nmsp_tuple_baseInterface::get<integralSequence>(_tuple)...);
}
template <typename... Types>
auto reverse_(const _nmsp_tuple_baseInterface::tuple<Types...>& _tuple)
{
// sizeof...(Types) == N --> IntegerSequenceReverse::Integer_Sequence_Reverse_T --> std::integer_sequence
// IntegerSequenceReverse::Integer_Sequence_Reverse_T() --> 产生一个std::integer_sequence()临时对象
return reverseHelper(_tuple, IntegerSequenceReverse::Integer_Sequence_Reverse_T<size_t, sizeof...(Types)>());
}
void test()
{
_nmsp_tuple_baseInterface::tuple<float, double, string> mytuple1(float(1.2), double(2.5), string("hello"));
cout << typeid(typename pop_front_type<decltype(mytuple1)>::type).name() << endl;
cout << "**********************************" << endl;
// auto == _nmsp_tuple_baseInterface::tuple
auto mytuple2 = _nmsp_tuple_extentInterface::push_front(mytuple1, int(1));
cout << ".........................................." << endl;
auto mytuple3 = _nmsp_tuple_extentInterface::push_front_recursive(mytuple1, int(1));
cout << "**********************************" << endl;
// auto == _nmsp_tuple_baseInterface::tuple
auto mytuple4 = _nmsp_tuple_extentInterface::push_back(mytuple1, int(1));
cout << "**********************************" << endl;
auto mytuple5 = _nmsp_tuple_extentInterface::pop_front(mytuple3);
cout << "**********************************" << endl;
auto mytuple6 = _nmsp_tuple_extentInterface::reverse(mytuple2);
cout << typeid(mytuple6).name() << endl;
cout << "**********************************" << endl;
// 测试Integer_Sequence_Reverse_T:
IntegerSequenceReverse::Integer_Sequence_Reverse_T<int, 5> tmpObj;
cout << typeid(decltype(tmpObj)).name() << endl;
// 利用reverse_实现tuple的反转:
auto mytuple7 = _nmsp_tuple_extentInterface::reverse_(mytuple2);
cout << typeid(mytuple6).name() << endl;
cout << "**********************************" << endl;
}
}
int main()
{
_nmsp_tuple_baseInterface::test();
_nmsp_tuple_extentInterface::test();
return 0;
}
#include
#include
using namespace std;
namespace _nmsp
{
/* .. 该函数模板用来识别类中是否含有tuple_fun()函数,即判断该类是否时tuple类 .. */
template <typename T, typename U = std::void_t<>>
class HasMemTupleFunc : public std::false_type
{ };
// 特化版本:std::declval().tuple_func()可在不构建T类对象的情况下,达到构建了对象的效果
template <typename T>
class HasMemTupleFunc<T, std::void_t<decltype(std::declval<T>().tuple_func())>> : public std::true_type
{ };
/* ......................................... */
// 泛化版本:只声明不定义,用来引出特化版本
template <typename... Types>
class tuple;
// 特化版本1:用来递归实例化的过程
template <typename First, typename... Others>
class tuple<First, Others...>
{
public:
First first;
tuple<Others...> others;
public:
// 默认构造函数:
tuple()
{
cout << "tuple::tuple()" << endl;
}
// 有参构造函数(模板):
// 这里使用“万能引用 + std::forward”,可还原原始传入的实参的左右值属性,即实现“完美转发”
// 通过“完美转发”,可在拷贝过程中,对右值进行移动拷贝,故可提高程序的效率
template <typename _First, typename... _Others
, typename = std::enable_if_t< !HasMemTupleFunc<_First>::value >>
tuple(_First&& _first, _Others&&... _others) : first(std::forward<_First>(_first))
, others(std::forward<_Others>(_others)...)
{
cout << "tuple::tuple(_First&& _first, _Others&&... _others)" << endl;
}
// 拷贝构造函数:
/*
// 如果形参用const修饰,编译器会报错
// 原因:本该在拷贝构造时调用该函数,结果编译器却调用了有参构造函数,导致出现错误
tuple(const tuple& _tuple) : first(_tuple.first), others(_tuple.others)
{
cout << "tuple::tuple(const tuple& _tuple)" << endl;
}
*/
/*
// 解决方法,将形参的const修饰符,拿掉
// 但存在新的问题:无法正常拷贝“常量tuple对象”或“显式转换得到的tuple对象”
tuple(tuple& _tuple) : first(_tuple.first), others(_tuple.others)
{
cout << "tuple::tuple(const tuple& _tuple)" << endl;
}
*/
// 解决方法:
// 1、在tuple类中引入一个tuple类专属的成员函数,用来识别tuple类
// 2、在有参构造函数(模板)的模板参数列表中,加入一个模板参数
// typename = std::enable_if_t::value
// ,表示只有在传入的第一个实参不是tuple类型时,才会调用高函数
tuple(const tuple<First, Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
{
cout << "tuple::tuple(const tuple& _tuple)" << endl;
}
// 拷贝构造函数模板:
// 当调用拷贝构造时,_First参数类型与First不一致时,则会调用“拷贝构造函数模板”
template <typename _First, typename... _Others>
tuple(const tuple<_First, _Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
{
cout << "tuple<_First, _Others...>::tuple(const tuple<_First, _Others...>& _tuple)" << endl;
}
public:
void tuple_func() {}
};
// 特化版本2:作为递归结束的出口
template <>
class tuple<>
{
public:
tuple() { cout << "tuple<>::tuple()" << endl; }
tuple(const tuple<>&) { cout << "tuple<>::tuple(const tuple<>&)" << endl; }
};
/* 通过get函数得到tuple中的第index个元素:*/
// 泛化版本:用于递归实例化展开
template <size_t index>
class GetHelper
{
public:
template <typename First, typename... Others>
static auto getHelper(const tuple<First, Others...>& _tuple)
{
return GetHelper<index - 1>::getHelper(_tuple.others);
}
};
// 特化版本:用于递归结束的出口
template <>
class GetHelper<0>
{
public:
template <typename First, typename... Others>
static auto getHelper(const tuple<First, Others...>& _tuple)
{
return _tuple.first;
}
};
// 函数模板:用于对外调用的接口
template <size_t index, typename... Types>
auto get(const tuple<Types...>& _tuple)
{
return GetHelper<index>::getHelper(_tuple);
}
/* 通过make_tuple函数,可将不同类型的数据打包转化为tuple类型:*/
template <typename... Types>
auto make_tuple(Types&&... args) // 形参是万能引用
{
return tuple<std::decay_t<Types>...>(std::forward<Types>(args)...);
}
// 这里make_tuple的类型推导技术:可根据传入的实参自动推导出元素的类型,并将“退化”后的类型放入tuple中
}
int main()
{
_nmsp::tuple<int, float, double> mytuple1;
cout << "*********************************************" << endl;
_nmsp::tuple<int, float, double, string> mytuple2(int(1), float(2.1), double(3.5), string("hello"));
cout << "*********************************************" << endl;
_nmsp::tuple<int, float, double, string> mytuple3(mytuple2);
cout << "...当mytuple4==>First==double、mytuple2==>First==int时,类型不一致时,需通过调用“拷贝构造函数模板”完成拷贝 ..." << endl;
_nmsp::tuple<double, float, double, string> mytuple4(mytuple2);
cout << "*********************************************" << endl;
_nmsp::tuple<double> mytuple5(3.5);
cout << "---------------------------------------------" << endl;
// 这里第三个参数的拷贝,调用的是“拷贝构造函数模板”
_nmsp::tuple<int, float, _nmsp::tuple<double>> mytuple6(int(1), float(2.1), mytuple5);
cout << "---------------------------------------------" << endl;
_nmsp::tuple<int, double> mytuple5_(3.5);
_nmsp::tuple<_nmsp::tuple<int, double>> mytuple6_(mytuple5);
// 这里注意:如果嵌套的tuple中,存在两个及以上的类型,则会报错,原因是调用拷贝构造函数模板时
//,First == _nmsp::tuple 与 _First == int,不一致导致的
/* 这里需要进一步有待完善。。。 */
cout << "*********************************************" << endl;
cout << _nmsp::get<0>(mytuple6) << endl;
cout << _nmsp::get<1>(mytuple6) << endl;
cout << _nmsp::get<0>(_nmsp::get<2>(mytuple6)) << endl;
cout << "*********************************************" << endl;
auto mytuple7 = _nmsp::make_tuple(int(1), float(2.1), double(3.5), string("hello"));
cout << "*********************************************" << endl;
return 0;
}
#include
#include
using namespace std;
namespace _nmsp
{
// 泛化版本:只声明不定义,用来引出特化版本
template <typename... Types>
class tuple;
// 特化版本1:用来递归实例化的过程
template <typename First, typename... Others>
class tuple<First, Others...>
{
public:
First first;
tuple<Others...> others;
public:
// 默认构造函数:
tuple()
{
cout << "tuple::tuple()" << endl;
}
// 有参构造函数:
// 这里使用“万能引用 + std::forward”,可还原原始传入的实参的左右值属性,即实现“完美转发”
// 通过“完美转发”,可在拷贝过程中,对右值进行移动拷贝,故可提高程序的效率
template <typename _First, typename... _Others>
tuple(_First&& _first, _Others&&... _others) : first(std::forward<_First>(_first)), others(std::forward<_Others>(_others)...)
{
cout << "tuple::tuple(_First&& _first, _Others&&... _others)" << endl;
cout << first << endl;
}
};
// 特化版本2:作为递归结束的出口
template <>
class tuple<>
{
public:
tuple() { cout << "tuple<>::tuple()" << endl; }
tuple(const tuple<>&) { cout << "tuple<>::tuple(const tuple<>&)" << endl; }
};
}
#include
#include
using namespace std;
namespace _nmsp
{
/* .. 该函数模板用来识别类中是否含有tuple_fun()函数,即判断该类是否时tuple类 .. */
template <typename T, typename U = std::void_t<>>
class HasMemTupleFunc : public std::false_type
{ };
// 特化版本:std::declval().tuple_func()可在不构建T类对象的情况下,达到构建了对象的效果
template <typename T>
class HasMemTupleFunc<T, std::void_t<decltype(std::declval<T>().tuple_func())>> : public std::true_type
{ };
/* ......................................... */
// 泛化版本:只声明不定义,用来引出特化版本
template <typename... Types>
class tuple;
// 特化版本1:用来递归实例化的过程
template <typename First, typename... Others>
class tuple<First, Others...>
{
public:
First first;
tuple<Others...> others;
public:
// 默认构造函数:
tuple()
{
cout << "tuple::tuple()" << endl;
}
// 有参构造函数(模板):
// 这里使用“万能引用 + std::forward”,可还原原始传入的实参的左右值属性,即实现“完美转发”
// 通过“完美转发”,可在拷贝过程中,对右值进行移动拷贝,故可提高程序的效率
template <typename _First, typename... _Others, typename = std::enable_if_t< !HasMemTupleFunc<_First>::value>>
tuple(_First&& _first, _Others&&... _others) : first(std::forward<_First>(_first)), others(std::forward<_Others>(_others)...)
{
cout << "tuple::tuple(_First&& _first, _Others&&... _others)" << endl;
}
// 拷贝构造函数:
/*
// 如果形参用const修饰,编译器会报错
// 原因:本该在拷贝构造时调用该函数,结果编译器却调用了有参构造函数,导致出现错误
tuple(const tuple& _tuple) : first(_tuple.first), others(_tuple.others)
{
cout << "tuple::tuple(const tuple& _tuple)" << endl;
}
*/
/*
// 解决方法,将形参的const修饰符,拿掉
// 但存在新的问题:无法正常拷贝“常量tuple对象”或“显式转换得到的tuple对象”
tuple(tuple& _tuple) : first(_tuple.first), others(_tuple.others)
{
cout << "tuple::tuple(const tuple& _tuple)" << endl;
}
*/
// 解决方法:
// 1、在tuple类中引入一个tuple类专属的成员函数,用来识别tuple类
// 2、在有参构造函数(模板)的模板参数列表中,加入一个模板参数`typename = std::enable_if_t::value>`,表示只有在传入的第一个实参不是tuple类型时,才会调用该函数
tuple(const tuple<First, Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
{
cout << "tuple::tuple(const tuple& _tuple)" << endl;
}
// 拷贝构造函数模板:
// 当调用拷贝构造时,两个_tuple的_First参数类型与First不一致时,则会调用“拷贝构造函数模板”
template <typename _First, typename... _Others>
tuple(const tuple<_First, _Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
{
cout << "tuple<_First, _Others...>::tuple(const tuple<_First, _Others...>& _tuple)" << endl;
}
public:
void tuple_func() {}
};
// 特化版本2:作为递归结束的出口
template <>
class tuple<>
{
public:
tuple() { cout << "tuple<>::tuple()" << endl; }
tuple(const tuple<>&) { cout << "tuple<>::tuple(const tuple<>&)" << endl; }
};
}
注意“拷贝构造函数”和“拷贝构造函数模板”的区别:(两者必须同时存在!!!)
/* 通过get函数得到tuple中的第index个元素:*/
// 泛化版本:用于递归实例化展开
template <size_t index>
class GetHelper
{
public:
template <typename First, typename... Others>
static auto getHelper(const tuple<First, Others...>& _tuple)
{
return GetHelper<index - 1>::getHelper(_tuple.others);
}
};
// 特化版本:用于递归结束的出口
template <>
class GetHelper<0>
{
public:
template <typename First, typename... Others>
static auto getHelper(const tuple<First, Others...>& _tuple)
{
return _tuple.first;
}
};
// 函数模板:用于对外调用的接口
template <size_t index, typename... Types>
auto get(const tuple<Types...>& _tuple)
{
return GetHelper<index>::getHelper(_tuple);
}
/* 通过make_tuple函数,可将不同类型的数据打包转化为tuple类型:*/
template <typename... Types>
auto make_tuple(Types&&... args) // 形参是万能引用
{
return tuple<std::decay_t<Types>...>(std::forward<Types>(args)...);
}
// 这里make_tuple的类型推导技术:可根据传入的实参自动推导出元素的类型,并将“退化”后的类型放入tuple中
/* pop_front_type类模板:从tuple中移除第一个类型 */
// 泛化版本:
template <typename Tuple>
class pop_front_type;
// t特化版本:
template <typename First, typename... Others>
class pop_front_type<_nmsp_tuple_baseInterface::tuple<First, Others...>>
{
public:
using type = _nmsp_tuple_baseInterface::tuple<Others...>;
};
/* push_front函数模板:向tuple的头插一个元素 */
// 普通实现方法:
template <typename... Types, typename insertType>
auto push_front(const _nmsp_tuple_baseInterface::tuple<Types...>& _tuple, const insertType& newElement)
{
return _nmsp_tuple_baseInterface::tuple<insertType, Types...>(newElement, _tuple);
}
// 递归方法:
// 1、递归结束的出口
template <typename insertType>
auto push_front_recursive(const _nmsp_tuple_baseInterface::tuple<>& _tuple, const insertType& newElement)
{
return _nmsp_tuple_baseInterface::tuple<insertType>(newElement);
}
// 2、递归实例化的过程:
template <typename First, typename... Others, typename insertType>
auto push_front_recursive(const _nmsp_tuple_baseInterface::tuple<First, Others...>& _tuple, const insertType& newElement)
{
return _nmsp_tuple_baseInterface::tuple<insertType, First, Others...>(newElement, push_front_recursive(_tuple.others, _tuple.first));
}
/* push_back函数模板:向tuple的头插一个元素 */
/*
//普通实现写法:不支持这种写法
template
auto push_back(const _nmsp_tuple_baseInterface::tuple& _tuple, const insertType& newElement)
{
return _nmsp_tuple_baseInterface::tuple(_tuple, newElement);
}
*/
// 递归方法:
// 1、递归结束的出口
template <typename insertType>
auto push_back_(const _nmsp_tuple_baseInterface::tuple<>& _tuple, const insertType& newElement)
{
return _nmsp_tuple_baseInterface::tuple<insertType>(newElement);
}
// 2、递归实例化的过程:
template <typename First, typename... Others, typename insertType>
auto push_back_(const _nmsp_tuple_baseInterface::tuple<First, Others...>& _tuple, const insertType& newElement)
{
return _nmsp_tuple_baseInterface::tuple<First, Others..., insertType>(_tuple.first, push_back(_tuple.others, newElement));
}
/* pop_front函数模板:从tuple中移除第一个元素 */
template <typename Tuple>
auto pop_front(const Tuple& _tuple)
{
return _tuple.others;
}
/* reverse函数模板:反转一个tuple中的元素顺序 */
// 递归方法:
// 1、递归结束的出口
auto reverse(const _nmsp_tuple_baseInterface::tuple<>&)
{
return _nmsp_tuple_baseInterface::tuple<>();
}
// 2、递归的过程
template <typename First, typename... Others>
auto reverse(_nmsp_tuple_baseInterface::tuple<First, Others...>& _tuple)
{
return push_back(reverse(_tuple.others), _tuple.first);
}
// 结合IntegerSequence_Reverse,实现reverse:
namespace IntegerSequenceReverse
{
/* 定义 IntegerSequence_pushBack 类模板(泛化和特化版本),用来实现“尾插”的功能: */
template <typename T, size_t newElement>
class IntegerSequence_pushFront; // 因不使用泛化版本,故只声明不定义
template <typename T, size_t... Elements, size_t newElement>
class IntegerSequence_pushFront<std::integer_sequence<T, Elements...>, newElement>
{
public:
using type = std::integer_sequence<T, newElement, Elements...>;
};
/* .................................... */
/* 自定义 Integer_Sequence 类模板(泛化和特化版本),用来实现make_integer_sequence的功能:*/
// 泛化版本:
template <typename T, size_t N>
class Integer_Sequence_Reverse
{
public:
// 依次遍历出N-1、...、3、2、1、0,并逐个通过IntegerSequence_pushBack尾插
using type = typename IntegerSequence_pushFront<typename Integer_Sequence_Reverse<T, N - 1>::type, N - 1>::type;
};
// 特化版本:
template <typename T>
class Integer_Sequence_Reverse<T, 1>
{
public:
using type = std::integer_sequence<T, 0>;
};
/* .................................... */
/* 定义别名模板:*/
template <typename T, size_t N>
using Integer_Sequence_Reverse_T = typename Integer_Sequence_Reverse<T, N>::type;
/* .................................... */
}
template <typename... Types, size_t... integralSequence>
auto reverseHelper(const _nmsp_tuple_baseInterface::tuple<Types...>& _tuple, std::integer_sequence<size_t, integralSequence...>)
{
// 这里将传入的逆序整型序列,作为get中的index,进而实现逆序
return make_tuple(_nmsp_tuple_baseInterface::get<integralSequence>(_tuple)...);
}
template <typename... Types>
auto reverse_(const _nmsp_tuple_baseInterface::tuple<Types...>& _tuple)
{
// sizeof...(Types) == N --> IntegerSequenceReverse::Integer_Sequence_Reverse_T --> std::integer_sequence
// IntegerSequenceReverse::Integer_Sequence_Reverse_T() --> 产生一个std::integer_sequence()临时对象
return reverseHelper(_tuple, IntegerSequenceReverse::Integer_Sequence_Reverse_T<size_t, sizeof...(Types)>());
}