c++11 总结-1

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()
3void 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);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值