c++_learning-模板元编程

模板元编程

  • 元编程:
  • 元函数:
    • 定义:
    • 数值元函数:
      • 编译期间,能够被调用的类模板:
      • constexpr修饰的函数:
      • constexpr修饰的变量模板:
    • 类型元函数:
    • 元函数总结:
  • 混合元编程:
    • 定义:
    • 混合元编程计算点积:
      • “常规的计算点积”与“混合元编程计算点积”的对比:
      • c++编译的两个阶段:
      • 类模板实例化:
      • 元编程中“计算完整性”的概念:
      • 注意:
      • inline静态成员变量:
  • 类型列表typelist实现:(类型计算范例)
    • 介绍:
    • 自定义实现typelist类型列表:
      • typelist的老式设计:列表头+嵌套列表
      • typelist的新式设计:
        • **实现基本的操作接口:**
        • **扩展的操作接口:**
          • 根据索引号查询typelist中某个元素,即find类模板:
          • 遍历typelist中sizeof最大的类类型,即get_maxsize类模板:
          • 反转typelist,即reverse类模板:
  • tuple的实现:(递归组合实现)
    • 元组的基础代码:
      • “泛化、特化、构造函数”的实现:
      • “拷贝构造函数、拷贝构造函数模板”的实现:
      • 实现获取tuple中元素的get接口:
      • std::make_tuple的实现:
    • 算法:
      • 从tuple中移除第一个类型pop_front_type:
      • 向tuple的开头和结尾插入一个元素push_front、push_back:
      • 从tuple中移除第一个元素pop_front:
      • 反转一个tuple中的元素顺序reverse:

元编程:

将各种计算从运行期提前至编译期,以达到提升运行时性能的目的,即是通过增加程序编译时间,来提升程序运行效率的编程手法。元编程中会使用到“递归”技术。

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;
}

constexpr修饰的函数:

#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;
}

constexpr修饰的变量模板:

#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类模板,实现的元编程就是靠“递归模板实例化”来驱动的。

  • 用using来定义类型别名的类模板(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;
}
  • using定义的变量模板,也可称为类型元函数。
#include 
using namespace std;
 
template <typename T>
using AddPoint = T*;

int main()
{
    AddPoint<const char> str = "hello";
    cout << typeid(str).name() << endl;

    return 0;
}

元函数总结:

可宽泛的认为:只要用于元编程中,且编译器期间能够被调用,都可以视为元函数(不避局限于类型元函数、数值元函数)。

混合元编程:

定义:

  1. 写出一个段元编程的代码;
  2. 编译器根据这段代码编译(生成)一段新的代码,实际程序真正的功能就是这段新代码;
  3. 编译器会对这段新代码进行编译,产生出最终的可执行程序;

混合元编程计算点积:

“常规的计算点积”与“混合元编程计算点积”的对比:

#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++代码,故元编程才会被看作“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;
}

元编程中“计算完整性”的概念:

  1. 状态变量:类模板中的模板参数;
  2. 迭代构造(循环构造):通过在类模板中融入递归编程技术来实现;
  3. 整数对象(整数运算):静态成员变量 或 枚举类型,其他功能类似于变量/常量。

注意:

  1. 元编程中,不能使用变量,编译期能接受的只有静态变量
  2. 传统意义上的分支和循环在元编程中,只能通过条件运算符、特化、递归等手段实现。

inline静态成员变量:

  • c++17开始,constexpr自带inline属性;

  • 使用枚举类型inline静态成员变量(c++11引入)相同,都不存在额外占用内存空间的问题 。

    #include 
    using namespace std;
    
    struct A
    {
        enum { value1 = 12 };
        static inline const int value2 = 12;
    };
    

类型列表typelist实现:(类型计算范例)

介绍:

一个类型容器,对类型提供了一系列操作(将类型看作数据来操作)。本质:一个类模板,用来表示一个列表,其中存放的是一堆类型。

自定义实现typelist类型列表:

typelist的老式设计:列表头+嵌套列表

#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;
}

typelist的新式设计:

实现基本的操作接口:
  1. 判断typelist中类类型是否为空,即is_empty类模板;
  2. 获取typelist中类类型的个数,即size类模板;
  3. 提取typelist中的首个类类型,即front类模板;
  4. 从typelist中剔除第一个类类型,即pop_front类模板;
  5. 向typelist头插一个类类型,即push_front类模板;
  6. 向typelist尾插一个类类型,即push_back类模板;
  7. 替换typelist中首个类类型,即replace_front类模板;
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故会报错
        */ 
    }
}
扩展的操作接口:
根据索引号查询typelist中某个元素,即find类模板:

c++_learning-模板元编程_第1张图片

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越界,则编译期会报错 
    }
}
遍历typelist中sizeof最大的类类型,即get_maxsize类模板:

c++_learning-模板元编程_第2张图片

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; 
    }
}
反转typelist,即reverse类模板:

c++_learning-模板元编程_第3张图片

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的实现:(递归组合实现)

元组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; }
    };
}

注意“拷贝构造函数”和“拷贝构造函数模板”的区别:(两者必须同时存在!!!)

  • “拷贝构造函数”被调用,说明:被拷贝的对象与待拷贝的对象的First参数类型是相同的。
  • “拷贝构造函数模板”被调用,则说明:被拷贝的对象与待拷贝的对象的First参数类型不同。

实现获取tuple中元素的get接口:

/* 通过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);
}

std::make_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中

算法:

从tuple中移除第一个类型pop_front_type:

/* 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...>;
};

向tuple的开头和结尾插入一个元素push_front、push_back:

/* 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));
}

从tuple中移除第一个元素pop_front:

/* pop_front函数模板:从tuple中移除第一个元素 */
template <typename Tuple>
auto pop_front(const Tuple& _tuple)
{	
    return _tuple.others;
}

反转一个tuple中的元素顺序reverse:

/* 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)>());
}

你可能感兴趣的:(c++,开发语言)