文章目录
1、让程序更简洁
1.1、类型推导
1、auto
2、decltype,后置语法(解决前置,参数尚未定义)
1.2、模板细节的改进
1、模板的别名,typedef 改成使用using
2、默认模板参数
template<typename T = int>
1.3、列表初始化
1、初始化列表的限制
1、私有或者保护的 非静态的数据成员
2、无基类
3、无虚函数
4、不能有{} 和 =
2、std::initilizer_list 的细节
3个接口 begin, size, end
高效:只是数据的引用
1.4 基于范围的for 循环
for_each 是算法
vector 迭代器是地址指针,如果中间添加数据,导致容量上限,重新申请内存,会到迭代器失效
1.5 std::funtion 和 bind
1、可调用对象
2、bind 可以绑定对应
/**
* 使用std::bind 有2个好处
* 1、可以将可调用对象和参数绑定,变成一个仿函数
* 2、可以多个参数变成一个参数的调用
*
* 占位符,是表示第几个参数
* 逻辑与, bind 表达式可以预览组合多个参数。例如:可以预览3个参数
*/
auto f = std::bind(std::logical_and<bool>(),
std::bind(std::greater<int>(),std::placeholders::_2,5),
std::bind(std::less_equal<int>(),
std::placeholders::_1,std::placeholders::_3));
1.6 lambda 表达式
优点
1、声明式编程风格,更直接,可读性和可维护性更高
2、简洁,开发高效
修改[=] 对应的变量,可以使用mutable
默认是const
1、没有捕获的可以转换成函数指针
2、有捕获的不可以
tuple
元组提供灵活的小结构体,tuple 的解析需要模板元的技巧
2、改进性能
2.1 右值引用
通过避免额外的拷贝来提高效率
/**
* 右值引用
*
* 田志泽 Tian zhize
* tianzhize137@163.com
*
* 优点
* 1、避免深拷贝,解决在拷贝构造时候深拷贝
*右值定义
* 1、右值是表示在表达完成时销毁的对象,判断条件是否可以取地址。具名的都是左值,不具名是右值
* 2、左值、将亡值、纯右值
* 3、将亡值:被移动的对象,T&& 返回值,std::move 返回值
* 4、纯右值:返回的临时变量,运算符产生的临时变量,字面量(0,1),lambda表达式
*
*/
常量+左值引用,是万能引用 这也是拷贝构造函数的写法
假设没有移动构造的情况下,Foo(const Foo &) 既可以接收左值,又可以接收右值
move & forward
1、引用折叠
/* std::move
* 1、将一个左值变成右值,主观上想让左值变成右值方式来使用,提高效率。
* 2、使用copy 效率很低
*
* std::forward
* 1、解决 嵌套调用时,类型转成左值的问题
* 2、实现 使用static_cast<T &&>() 转换,由于函数返回,所以不具名,无名的右值引用是右值。和 std::move 是一样。
* 3、引用折叠 &&
*/
/**
* 在类型推导的情况,&& ,引用折叠的情况
* 1、所有的右值引用,叠加到右值引用上,还是右值引用 int && && 还是右值引用
* 2、其他的全部都是左值引用
*/
2、使用static_cast<T &&> 进行强制转换成右值,move 就是将左值转换成右值
2.4 emplace_back 减少内存拷贝和移
* emplace_back
* 1、减少内存拷贝, 注意vector扩容的问题
* 2、emplace_back只会构造1次,而push_back 会进行构造并且进行拷贝
* 3、内部实现是 palcement new ,在指定的内存上进行构造
2.5 无序容器
unordered_map, unordered_set
3、消除重复,提高代码质量
总结:
c ++ 11 进一步增强了c++泛型编程的的能力,尤其是type_traits, 可变参数模板和tuple ,可以在编译期计算,消除重复定义,是程序更为简洁高效
1、实现了在编译期进行计算、查询、判断、转换,增加泛型编程的能力,很好的支持模板元编程
2、例如:可变模板参数,可以支持更多的函数,避免大量重复代码重载。
3、判断
- optional 的实现
- lazy 延迟调用
- dll 帮助类
- lambda 链式调用
- any类的实现
- function_traits
- variant 的实现
- ScopeGuard
- tuple_helper
名词:
圈复杂度(Cyclomatic complexity)是一种代码复杂度的衡量标准
3.1 type_traits 类型萃取
/**
* 类型萃取
*
* 田志泽 Tian zhize
* tianzhize137@163.com
*
* 什么是type traits
* 1、实现了在编译期进行计算、查询、判断、转换,增加泛型编程的能力,很好的支持模板元编程
*
* type traits 种类
* 1、简单的 intergral_constant,根据intergral_constant::value 来判断
* 2、判断 is_intergral, is_type ,这些都继承与intergral_constant
* 3、类型之间的关系,is_same, is_base_of, is_covertible,这些都继承与intergral_constant
* 4、类型的转换,remove_const, add_const, remvoe_reference 等。可以通过add_const<>::type 来改变类型
* 5、根据条件选择 ,conditional<>, 根据条件开启和关闭某种traits
*
* constexpr
* 表示常量。 const 只是表示不可修改
*
* operator double(){}
* 类型隐式转换,i = (double)d;
*
* std::result_of
* 可以获得可调用对象的类型,可以替代运算符中的运算推导
*
* enable_if
* 为ture 类型为T, 否则是void
*
*/
1、decay 可以去掉cv 和引用
// 使用去掉引用 和 cv 太长了
template <class U>
typename std::remove_cv<typename std::remove_reference<U>::type>::type* getA() {
using V = typename std::remove_cv<typename std::remove_reference<U>::type>::type;
return new V();
}
// 使用decay 衰退, 更加简洁
template <class U>
typename std::decay<U> * getV() {
using V = std::decay<U>;
return new V();
}
2、conditional , 选择类型
std::conditional<true,int,long>::type;
3、 resulte_of, decltype, 3种返回类型
//返回值
template <class F, class Args>
decltype((*(F*)0)(*(Args*)0)) func1(F f, Args a) {
return f(a);
}
template <class F, class Args>
auto func1(F f, Args a) -> decltype(f(a)){
return f(a);
}
template <class F, class Args>
typename std::result_of<F(Args)>::type func1(F f, Args a) {
return f(a);
}
4、enable_if 可以用于函数重载,如果是false 函数类型不支持
template <class T, class = typename std::enable_if<true>::type>
void func_enable_if(){
}
template <class T, class = typename std::enable_if<false,T>::type>
void func_enable_if2(){
}
5、is_same, is_base_of, is_convertible
/**
* 3、test is_same, is_base_of, is_covertible
*/
class A{};
class B :public A {
};
void test_is_between_type() {
std::cout << std::is_same<int,int>::value << std::endl;
std::cout << std::is_base_of<A,B>::value << std::endl;
std::cout << std::is_convertible<A*,B*>::value << std::endl;
}
3.2 可变模板参数
/**
* 可变模板参数
*
* 田志泽 Tian zhize
* tianzhize137@163.com
* 背景
* 1、c++11 之前只能是固定的模板参数
* 2、消除重复代码,不同的参数个数,需要定义多个函数重载实现
*
* 模板函数 可变模板参数展示
* 递归展开
* 1、常见的方式
* 2、需要有同名的终止函数
*
* 逗号+初始化列表展开
* 1、逗号列表,(exp,exp2) 会执行所有的表达是,但是最后等于exp2
* 2、可以initializer_list<int> {}
* 类 可变参数模板展示
* 模板特化展开
* 继承展开
*
* notice
* 1、继承时候最后定义成struct 不要是 class , 因为calss 有权限问题
*
* sizeof
* 使用sizeof...(args) 可以获取参数个数
*
*/
函数模板展开
1、函数模板展开(递归方式)
/**
* 展开参数包
* 1、递归方式
* 2、逗号分割符
*/
void print() {
}
template<class T,class ...Args>
void print(T t, Args ...args) {
cout << t << endl;
print(args...);
}
2、函数模板展开(逗号+初始化列表)
/**
* 逗号+初始化列表
*/
template<class U>
void print(U u) {
cout << u << endl;
}
template<class ...Args>
void func1(Args ...arg) {
int arr[] = {(print(arg),0)...}; //逗号+初始化列表
initializer_list<int> a{(print(arg),0)...}; //
//gcc 还不支持
//initializer_list<int> b{([&]{print(arg);}(),0)...}; //lambda
}
3、函数模板展开(enable_if常量参数, 递归中一种)
/**
* 遍历tuple
*/
template<int I = 0, class Tuple>
typename enable_if<I == tuple_size<Tuple>::value>::type printTp() {
}
template<int I = 0, class Tuple>
typename enable_if<I < tuple_size<Tuple>::value>::type printTp() {
printTp<I+1>();
}
类可变模板展开
1、通过特化展开
// 第一部分,前项声明,这是可变参数模板类
template <class ...Args>
class Sum {
};
// 第二部分,如何展开的部分
template <class First, class ...Rest>
class Sum<First, Rest ...> { //类上添加<> 表示特化
enum { value = Sum<First>::value + Sum<Rest...>::value};
};
// 第三部分,特化的终止类
template <class Last>
class Sum<Last> {
enum{ value = sizeof(Last)};
};
2、继承展开
/**
* 继承方法展开 可变参数模板类
* 1、notice 继承时候最后定义成struct 不要是 class , 因为calss 有权限问题
*/
// 第一部分前置声明
template<int ...>
class IndexSeq{};
// 第二部分
template<int N, int ... Rest>
struct MakeIndex : MakeIndex<N - 1, N-1, Rest...> {
};
// 第三部分,终止类
template<int ...Indexes>
struct MakeIndex<0, Indexes...> { //在N 等于 0的时候终止
typedef IndexSeq<Indexes...> type; //在基类中基类
};
void test_class_variable_template() {
using T = MakeIndex<3>::type;
cout << typeid(T).name() << endl;
}
//展开tuple
// 使用 Index 和 tuple 打印模板参数
template<int ...Indexes, class ... Args>
void helper_tuple(IndexSeq<Indexes...> index,tuple<Args...> tup) {
print(get<Indexes>(tup)...);
}
template <class ...Args>
void printArgs(Args ... args) {
//sizeof...(args) 可以获取参数个数
helper_tuple(typename MakeIndex<sizeof...(Args)>::type(),make_tuple(args...));
}
其他
template<class T, class ...Args>
T * instance(Args ... args) {
//存在拷贝问题, 存在性能消耗
//return new T(args...);
// forward
return new T(forward(args)...);
}
3.3 可变模板参数和type_taits 的综合应用
1、optional 的实现
1、内存对齐和 placement new, 申请内存aligned_storage
2、类型转换 operator bool()
3、void operator() (int a) ,解决数据依赖,由对象存储数据
struct A {
int t;
};
template <class T>
class Optional {
public:
template <class... Args>
T* getInstance(Args... args) {
return new(&m_data) T(args...);
}
~Optional() {
((T*)(&m_data))->~T();
}
// 类型转换
operator bool() {
//
return false;
}
//运算符重载
T& operator *() {
return *((T*)(&m_data));
}
// 仿函数
void operator() (int a) {
}
private:
using data_t = std::aligned_storage<sizeof(T), std::alignment_of<T>::value>;
data_t m_data;
};
void test_operator() {
Optional<A> a;
if(a) { //判断是否初始化,根据类型强转 ,operator bool()
*a; // 调用 T& operator *()
a(1);
}
}
lazy 延迟调用
1、利用 lambda 将参数, 或者bind
m_func = [&f, &args...] {return f(args...);}
m_func = std::bind(&f, std::forward<Args>(args)...);
dll 帮助类
解决的问题
1、每个调用dll 获取参数,需要声明方法,比较繁琐
2、利用 模板减少对函数的声明
3、利用 可变参数模板,可以完成函数带参数的调用
/**
* 实现 std::function = GetFunction<int(int,int)>("MAX");
* auto max = ExecFunction<int(int,int)> ("Max", 5, 8);
*/
template <class T>
std::function<T> GetFuntion(const std::string & name ) {
auto funcAddresss = GetProcAddress(m_hmod, name.c_str());
return std::function<T>((T*)funcAddress);
}
template <class T, class ...Args>
typename std::result_of<std::function<T>(Args...)>::type ExecFunction(const std::string &name, Args... args) {
return GetFuntion<T>(name)(std::forward<Args>(args)...);
}
lambda 链式调用
1、使用lambda 延迟调用
2、每次调用 then 返回task 对象,新对象先执行之前的task 的func, 然后调用自己f
3、调用过程 task.then({调用1}).then({调用2}).run(1); 调用1先执行 ,在执行调用2, run 的参数是调用1的
可以简单压栈过程,调用1被第一个压栈,但是调用是dfs递归调用,这样调用1就被优先调用
/**
* 再次编写一次加强记忆
*/
template <class T>
class TaskA;
template <class R, class ...Args>
class TaskA<R(Args...)> {
public:
TaskA(std::function<R(Args...)> &&f) : m_fun(f){}
TaskA(std::function<R(Args...)> &f) : m_fun(f){}
R run(Args&&...args) {
return m_fun(std::forward<Args>(args)...);
}
template<class F>
auto then(F && f) -> TaskA<typename std::result_of<F(R)>::type(Args...)>{
// 获取F的返回值
using NewType = typename std::result_of<F(R)>::type(Args...);
// 新创建一个task 对象,先执行之前的task 的func, 然后调用自己f
auto newFun = [&f,this](Args&&...args){
auto ret = m_fun(std::forward<Args>(args)...);
return f(ret);
};
return TaskA<NewType>(newFun);
}
std::function<R(Args...)> m_fun;
};
void test_lambda_task() {
//调用过程 task.then({调用1}).then({调用2}).run(1);
// 套娃,没添加一个then 就套一层。执行过程是,先执行m_fun, 然后在执行fun;
Task<int(int,int)> task{[](int a,int b) {
std::cout << 1 << std::endl;
return a + 1;
}};
auto task1 = task.then([](int a)->double {
std::cout << 2 << std::endl;
return a + 2;
});
auto task2 = task1.then([](double a) {
std::cout << 3 << std::endl;
return a + 2;
});
task2.run(1,2);
}
any类的实现
1、类型存储,使用base 进程存储,子类中存储value
2、通过typeid 获取类型的type_index,存储到any 中,在cast 时候先判断type_index 是否相同
3、如果相同,将base 转换 dynamic_cast
class Any {
public:
Any(): m_typeInfo(typeid(void)){}
//通过构造 模板,
// 限制不能是Any 类作为参数,因为是拷贝构造应该处理的
template <class U,
class = typename std::enable_if<!std::is_same<typename std::decay<U>::type, Any>::value, U>::type>
Any(U&& u)
: m_typeInfo(type_index(typeid(typename decay<U>::type))),
m_base(new Derived<typename std::decay<U>::type>(u)) {
}
//更加tpyeinfo 来确定是否相同
template<class U>
bool is() {
return type_index(typeid(typename decay<U>::type)) == m_typeInfo;
}
template<class U>
U& AnyCast() {
if(!is<U>()) {
throw bad_cast();
}
auto d = dynamic_cast<Derived<U>*>(m_base.get());
if (d) {
return d->value;
} else {
throw bad_cast();
}
}
private:
struct Base {
virtual ~Base(){}
};
template<class T>
struct Derived : public Base
{
//构造
Derived(T && t) : value(std::forward(t)){}
Derived(T & t) : value(t){}
T value;
};
unique_ptr<Base> m_base;
type_index m_typeInfo;
};
void test_any() {
Any a(1);
int b = a.AnyCast<int>();
}
function_traits
/**
* 实现一个Any类
*
* 田志泽 Tian zhize
* tianzhize137@163.com
*
*
*
* 实现function_traits的关键技术
* 要通过模板特化和可变参数模板来获取函数类型和返回类型。
* 先定义一个基本的function_traits的模板类:
* template<typename T>
* struct function_traits;
* 再通过特化,将返回类型和可变参数模板作为模板参数,就可以获取函数类型、函数返回值和参数的个数了。
*
* 如:
* int func(int a, string b);
* ## 获取函数类型
* function_traits<decltype(func)>::function_type; // int __cdecl(int, string)
* # 获取函数返回值
* function_traits<decltype(func)>::return_type; // int
* # 获取函数的参数个数
* function_traits<decltype(func)>::arity; // 2
* # 获取函数第一个入参类型
* function_traits<decltype(func)>::args<0>::type; // int
* # 获取函数第二个入参类型
* function_traits<decltype(func)>::args<1>::type; // string
*/
#include <iostream>
#include <functional>
#include <type_traits> //类型萃取
#include <tuple>
#include <typeindex> //typeid
#include <memory> //ptr
using namespace std;
/**
* 实现 funtion_traits
*/
template <class T>
class function_traits;
//通过特化获取返回值
// 基本特化版本
template<typename ReturnType, typename... Args>
struct function_traits<ReturnType(Args...)>{
enum { arity = sizeof...(Args) };
using return_type = ReturnType;
using function_type = ReturnType(Args...);
using stl_function_type = std::function<function_type>;
using pointer = ReturnType(*)(Args...);
template<size_t I>
struct args
{
static_assert(I < arity, "index is out of range, index must less than sizeof Args");
using type = typename std::tuple_element<I, std::tuple<Args...>>::type;
};
using tuple_type = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
using bare_tuple_type = std::tuple<std::remove_const_t<std::remove_reference_t<Args>>...>;
};
//函数指针
template<typename ReturnType, typename... Args>
struct function_traits<ReturnType(*)(Args...)> : function_traits<ReturnType(Args...)> {};
//function
template<typename ReturnType, typename... Args>
struct function_traits<std::function<ReturnType(Args...)>> : function_traits<ReturnType(Args...)> {};
// 成员函数
#define FUNCTION_TRAITS(...)\
template <typename ReturnType, typename ClassType, typename... Args>\
struct function_traits<ReturnType(ClassType::*)(Args...) __VA_ARGS__> : function_traits<ReturnType(Args...)>{};\
FUNCTION_TRAITS()
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)
// 函数对象
template<typename Callable>
struct function_traits : function_traits<decltype(&Callable::operator())> {};
//强转成 std::function
template<typename Function>
typename function_traits<Function>::stl_function_type to_function(const Function& lambda)
{
return static_cast<typename function_traits<Function>::stl_function_type>(lambda);
}
//强转成 std::function
template<typename Function>
typename function_traits<Function>::stl_function_type to_function(Function&& lambda)
{
return static_cast<typename function_traits<Function>::stl_function_type>(std::forward<Function>(lambda));
}
//强转成 函数指针
template<typename Function>
typename function_traits<Function>::pointer to_function_pointer(const Function& lambda)
{
return static_cast<typename function_traits<Function>::pointer>(lambda);
}
void func(int a,int b) {
}
template<typename T>
void printType()
{
cout << typeid(T).name() << endl;
};
float(*cast_func)(int, int, int, int);
float free_function(const string& a, int b)
{
return (float)a.size() / b;
}
struct AA
{
int f(int a, int b)volatile { return a + b; }
int operator()(int)const { return 0; }
};
void test_function_traits()
{
cout << "----------- 2 ----------" << endl;
//lambda
auto f = [](int a) {return a; };
//函数
printType<function_traits<decltype(f)>::function_type>();
//function
printType<function_traits<std::function<int(int)>>::function_type>();
//函数
printType<function_traits<decltype(free_function)>::function_type>();
//函数指针
printType<function_traits<decltype(cast_func)>::function_type>();
//可调用对象
printType<function_traits<AA>::function_type>();
//成员函数
using T = decltype(&AA::f);
printType<T>();
printType<function_traits<decltype(&AA::f)>::function_type>();
static_assert(std::is_same<function_traits<decltype(f)>::return_type, int>::value, "");
}
variant 的实现
支持制定多种类型的复用,很类似union 的用法,内存也是最大类型的大小,并行内存对齐
制定几种类型,可以存放制定类型的数据
1、取类型size的最大值,递归 conditional<sizeof(T) < MaxSize<Args…>::value
2、检查类型 递归,conditional ,利用is_same 判断
3、std::alignment_of 对齐内存,然后根据MaxSize 来获取大小
4、记录下来当前的type_index, 通过type_id 来获取
/**
* 去类型的最大值(递归)、继承于integral_constant<int, sizeof(T)
*/
template <class T, class... Args>
struct MaxSize : integral_constant<int, sizeof(T) < MaxSize<Args...>::value ? MaxSize<Args...>::value : sizeof(T)> {
using maxType = typename std::conditional<sizeof(T) < MaxSize<Args...>::value, typename MaxSize<Args...>::maxType, T>;
};
template <class T>
struct MaxSize<T> : integral_constant<int, sizeof(T)> {
using maxType = T;
};
/**
* 检查类型和缓冲区创建对象
* conditional
*/
template <class T, class... Args>
struct CheckType;
template <class T, class Head, class... Rest>
struct CheckType<T, Head, Rest...>
: std::conditional<std::is_same<T, Head>::value, std::true_type, typename CheckType<T, Rest...>::type> {};
template <class T>
struct CheckType<T> : std::false_type {};
/**
* Variant
*/
template <class T, class... Args>
struct Variant {
//只能是在类型中才可以构造
template <class U, class = typename std::enable_if<CheckType<typename std::decay<U>::type, T, Args...>::type::value,
U>::type>
Variant(U&& u) :m_typeIndex(typeid(typename std::decay<U>::type)) {
new(&m_data) (typename std::decay<U>::type)(u);
}
template<class U>
bool is() {
return type_index(typeid(U)) == m_typeIndex;
}
template<class U>
U Get() {
if(!is<U>()) {
throw bad_cast();
}
return (*(U*)&m_data);
}
// 内存数据m_data;
using data_t = std::aligned_storage<MaxSize<T, Args...>::value, std::alignment_of<typename MaxSize<T, Args...>::type>::value>;
data_t m_data;
type_index m_typeIndex;
};
int main() {
Variant<string,double,int> a = 1;
int b = a.Get<int>();
system("pause");
}
ScopeGuard
利用RAII 机制,在构造时候获取资源,在析构的时候释放资源
1、一般存储的是 function , 等到析构的时候释放
2、lock_guard 就是存储 lock
在考虑下
默认构造、拷贝构造、赋值运算的意义,没有意义就去掉
tuple_helper
- 递归方式遍历打印
- 通过索引序列打印
- 根据类型获取索引值
- 运行期根据索引获取
模板很重要的是提取类型,例如:tuple<Args…>,用下面的的方式就可以提前Args… 类型
#include <iostream>
#include <tuple>
#include <typeinfo>
using namespace std;
/**
* 递归方式遍历打印, tuple 打印很关键需要Index, 需要常量N 来获取
* TupleHelper
*/
template<class Tuple, int N>
struct TupleHelper {
static void print(const Tuple &t) {
TupleHelper<Tuple,N-1>::print(t);
cout << std::get<N-1>(t) << endl;
}
};
template<class Tuple>
struct TupleHelper<Tuple,1> {
static void print(const Tuple &t) {
cout << std::get<0>(t) << endl;
}
};
void test_print() {
tuple<int , string ,double> t = make_tuple<int , string ,double>(1,"a",1);
TupleHelper<decltype(t),tuple_size<decltype(t)>::value>::print(t);
}
/**
* 通过索引序列打印
* 索引序列是采用的继承的方式,构建索引,展开的Index,可以使用递归,但是一般使用的逗号+初始化列表
*/
template <int ...Args>
class Index {
};
template <int N, int ...Args>
struct MakeIndex : MakeIndex<N-1,N-1,Args...> {
};
template<int ...Args>
struct MakeIndex<0,Args...> {
using type = Index<Args...>;
};
//把索引分开
template<class U>
void print(U u) {
cout << u << endl;
}
template <class Tuple,int ...Args>
void printIndexTuple(Index<Args...>&& index,const Tuple &t) {
int arr[] = {(print(get<Args>(t)),0)...};
}
template<class ...Args>
void index_tuple_print(const tuple<Args...> &s) {
printIndexTuple(typename MakeIndex<sizeof...(Args)>::type(),s);
}
void test_index_tuple_print() {
tuple<int , string ,double> t = make_tuple<int , string ,double>(1,"2",3);
index_tuple_print<int , string ,double>(t);
}
/**
* 根据类型获取索引值
* 判断类型是否相同,如果相同获取到index
*/
template <int N,class T,class ...Rest>
struct GetIndex;
template <int N,class T,class Head, class ...Rest>
struct GetIndex<N,T,Head, Rest...> : conditional<is_same<T,Head>::value,integral_constant<int,N> ,GetIndex<N+1,T,Rest...>>::type{
};
template <int N,class T>
struct GetIndex<N,T> : integral_constant<int,-1>{
};
// 模板很重要的是提取类型,例如:tuple<Args...>,用下面的的方式就可以提前Args... 类型
template<class T,class ...Args>
void get_index_tuple(const tuple<Args...> &s) {
cout <<"type" << typeid(T).name() <<" index of" << GetIndex<0,T,Args...>() << endl;
}
void test_get_index() {
tuple<int , string ,double> t = make_tuple<int , string ,double>(1,"2",3);
get_index_tuple<string>(t);
}
/**
* 运行期根据索引获取
* 函数递归,通过函数重载如果 K 小于 tuple_size 就可以继续递归,通过参数和K进行比较,如果相同就返回。
*/
template<int K, class Tuple>
typename enable_if<K == tuple_size<Tuple>::value>::type
GetArgIndex(int index, const Tuple &t) {
}
template<int K, class Tuple>
typename enable_if<K < tuple_size<Tuple>::value>::type
GetArgIndex(int index, const Tuple &t) {
if(index == K) {
cout << get<K>(t) << endl;
} else {
GetArgIndex<K+1>(index,t);
}
}
void test_run_index() {
tuple<int , string ,double> t = make_tuple<int , string ,double>(1,"2",3);
int a = 1;
GetArgIndex<0>(a,t);
}
/**
* 反转tuple
* 1、反转的index
* 2、返回值,前置语句无法判断,延迟decltype( make_tuple())
*/
template<int... Indexs,class Tuple>
auto reverseTupleImp(const Tuple& t, Index<Indexs...> index) -> decltype(make_tuple(get<Indexs>(t)...)) {
return make_tuple(get<Indexs>(t)...);
}
template<class ...Args>
auto reverseTuple(const tuple<Args...> &t) -> decltype(reverseTupleImp(move(t),typename MakeIndex<sizeof...(Args)>::type())) {
return reverseTupleImp(t,typename MakeIndex<sizeof...(Args)>::type());
}
void test_reverse_tuple() {
tuple<int , string ,double> t = make_tuple<int , string ,double>(1,"2",3);
auto rt = reverseTuple(t);
}