c++_learning-模板元编程

news2025/3/3 17:55:04

模板元编程

  • 元编程:
  • 元函数:
    • 定义:
    • 数值元函数:
      • 编译期间,能够被调用的类模板:
      • 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 <iostream>
    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 <iostream>
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 <iostream>
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 <iostream>
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 <iostream>
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 <iostream>
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 <iostream>
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 <iostream>
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 <iostream>
    using namespace std;
    
    struct A
    {
        enum { value1 = 12 };
        static inline const int value2 = 12;
    };
    

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

介绍:

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

自定义实现typelist类型列表:

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

#include <iostream>
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<tylist2>::type).name() << endl;
        //	Error:因_nmsp_baseInterface::front<tylist2>此时调用的是泛化版本的front类模板
        //,其内部并未定义type故会报错

        using tylist2_delete1 = _nmsp_baseInterface::pop_front<tylist2>::type;
        //  Error:因_nmsp_baseInterface::pop_front<tylist2>此时调用的是泛化版本的pop_front类模板
        //,其内部并未定义type故会报错
        */ 
    }
}
扩展的操作接口:
根据索引号查询typelist中某个元素,即find类模板:

在这里插入图片描述

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类模板:

在这里插入图片描述

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类模板:

在这里插入图片描述

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 <iostream>
#include <string> 
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<T>().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<First, Others...>::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<First, Others...>::tuple(_First&& _first, _Others&&... _others)" << endl;
        }

        // 拷贝构造函数: 
        /*
		// 如果形参用const修饰,编译器会报错
		// 原因:本该在拷贝构造时调用该函数,结果编译器却调用了有参构造函数,导致出现错误
		tuple(const tuple<First, Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
		{
			cout << "tuple<First, Others...>::tuple(const tuple<First, Others...>& _tuple)" << endl;
		}
		*/
        /*
		// 解决方法,将形参的const修饰符,拿掉
		// 但存在新的问题:无法正常拷贝“常量tuple对象”或“显式转换得到的tuple对象”
		tuple(tuple<First, Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
		{
			cout << "tuple<First, Others...>::tuple(const tuple<First, Others...>& _tuple)" << endl;
		}
		*/
        // 解决方法:
        // 1、在tuple类中引入一个tuple类专属的成员函数,用来识别tuple类
        // 2、在有参构造函数(模板)的模板参数列表中,加入一个模板参数
        // typename = std::enable_if_t<!HasMemTupleFunc<_First>::value
        // ,表示只有在传入的第一个实参不是tuple类型时,才会调用高函数
        tuple(const tuple<First, Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
        {
            cout << "tuple<First, Others...>::tuple(const tuple<First, Others...>& _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<index>函数得到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<int, double> 与 _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 <typename... Types, typename insertType>
	auto push_back(const _nmsp_tuple_baseInterface::tuple<Types...>& _tuple, const insertType& newElement)
	{
		return _nmsp_tuple_baseInterface::tuple<insertType, Types...>(_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>中的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<size_t, N> --> std::integer_sequence<size_t, N-1, N-2, ..., 0>
        // IntegerSequenceReverse::Integer_Sequence_Reverse_T<size_t, N>() --> 产生一个std::integer_sequence<size_t, N-1, N-2, ..., 0>()临时对象
        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<int, float, double, string> 
        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<float, double, string, int> 
        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 <iostream>
#include <string> 
using namespace std;

namespace _nmsp
{
    /* .. 该函数模板用来识别类中是否含有tuple_fun()函数,即判断该类是否时tuple类 .. */
    template <typename T, typename U = std::void_t<>>
    class HasMemTupleFunc : public std::false_type
    { };
    // 特化版本:std::declval<T>().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<First, Others...>::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<First, Others...>::tuple(_First&& _first, _Others&&... _others)" << endl;
        }

        // 拷贝构造函数: 
        /*
        // 如果形参用const修饰,编译器会报错
        // 原因:本该在拷贝构造时调用该函数,结果编译器却调用了有参构造函数,导致出现错误
        tuple(const tuple<First, Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
        {
        	cout << "tuple<First, Others...>::tuple(const tuple<First, Others...>& _tuple)" << endl;
        }
        */
        /*
        // 解决方法,将形参的const修饰符,拿掉
        // 但存在新的问题:无法正常拷贝“常量tuple对象”或“显式转换得到的tuple对象”
        tuple(tuple<First, Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
        {
        	cout << "tuple<First, Others...>::tuple(const tuple<First, Others...>& _tuple)" << endl;
        }
        */
        // 解决方法:
        // 1、在tuple类中引入一个tuple类专属的成员函数,用来识别tuple类
        // 2、在有参构造函数(模板)的模板参数列表中,加入一个模板参数
        // typename = std::enable_if_t<!HasMemTupleFunc<_First>::value
        // ,表示只有在传入的第一个实参不是tuple类型时,才会调用高函数
        tuple(const tuple<First, Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
        {
        	cout << "tuple<First, Others...>::tuple(const tuple<First, Others...>& _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<index>函数得到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<int, double> 与 _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 <iostream>
#include <string>
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<First, Others...>::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<First, Others...>::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 <iostream>
#include <string> 
using namespace std;

namespace _nmsp
{
    /* .. 该函数模板用来识别类中是否含有tuple_fun()函数,即判断该类是否时tuple类 .. */
    template <typename T, typename U = std::void_t<>>
    class HasMemTupleFunc : public std::false_type
    { };
    // 特化版本:std::declval<T>().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<First, Others...>::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<First, Others...>::tuple(_First&& _first, _Others&&... _others)" << endl;
        }

        // 拷贝构造函数: 
        /*
        // 如果形参用const修饰,编译器会报错
        // 原因:本该在拷贝构造时调用该函数,结果编译器却调用了有参构造函数,导致出现错误
        tuple(const tuple<First, Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
        {
        	cout << "tuple<First, Others...>::tuple(const tuple<First, Others...>& _tuple)" << endl;
        }
        */
        /*
        // 解决方法,将形参的const修饰符,拿掉
        // 但存在新的问题:无法正常拷贝“常量tuple对象”或“显式转换得到的tuple对象”
        tuple(tuple<First, Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
        {
        	cout << "tuple<First, Others...>::tuple(const tuple<First, Others...>& _tuple)" << endl;
        }
        */
        // 解决方法:
        // 1、在tuple类中引入一个tuple类专属的成员函数,用来识别tuple类
        // 2、在有参构造函数(模板)的模板参数列表中,加入一个模板参数`typename = std::enable_if_t<!HasMemTupleFunc<_First>::value>`,表示只有在传入的第一个实参不是tuple类型时,才会调用该函数
        tuple(const tuple<First, Others...>& _tuple) : first(_tuple.first), others(_tuple.others)
        {
        	cout << "tuple<First, Others...>::tuple(const tuple<First, Others...>& _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<index>函数得到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 <typename... Types, typename insertType>
auto push_back(const _nmsp_tuple_baseInterface::tuple<Types...>& _tuple, const insertType& newElement)
{
	return _nmsp_tuple_baseInterface::tuple<insertType, Types...>(_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>中的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<size_t, N> --> std::integer_sequence<size_t, N-1, N-2, ..., 0>
    // IntegerSequenceReverse::Integer_Sequence_Reverse_T<size_t, N>() --> 产生一个std::integer_sequence<size_t, N-1, N-2, ..., 0>()临时对象
    return reverseHelper(_tuple, IntegerSequenceReverse::Integer_Sequence_Reverse_T<size_t, sizeof...(Types)>());
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1107118.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++基础——内存分区模型

1 概述 C程序在执行是&#xff0c;将内存大致分为4个区域&#xff1a; 代码区&#xff1a;用于存放二进制代码&#xff0c;由操作系统进行管理全局区&#xff1a;存放全局变量和静态变量及常量栈区&#xff1a;由编译器自动分配释放&#xff0c;存放函数的参数、局部变量等堆…

电脑版便签软件下载用哪个?

在面对每天繁忙的工作日程&#xff0c;电脑是许多上班族不可或缺的工作助手&#xff0c;而一款得心应手的电脑便签软件&#xff0c;更是可以帮助大家记录、提醒、督促各项任务按时完成的得力助手。那么&#xff0c;究竟在众多的电脑便签软。件中&#xff0c;哪一位能够真正成为…

你真的理解“感受野”了吗?

大家好啊&#xff0c;我是董董灿。 在卷积神经网络中&#xff0c;有一个非常重要且绕不开的概念叫做卷积的“感受野”。 我刚开始学习卷积的时候&#xff0c;仅仅把“感受野”理解为感受视野&#xff0c;没错就是文字上的理解。 但随着后来工作的深入&#xff0c;慢慢发现感…

pytorch的安装【全官网流程】

1.准备python环境 python环境需要看pytorch上说明的版本本文用的是python3.9 conda create -n pytorch39 python3.92.安装pytorch【要使用GPU的先安装步骤3的CUDA在安装这个】 pytorch官方地址 &#xff08;1&#xff09;官方指出了python版本&#xff1a; &#xff08;2…

微信私域怎么高效转化?看看这款系统!

在今天的数字化时代&#xff0c;私域流量已经成为企业与个人创业者获取竞争优势的重要手段。而微信作为中国最大的社交平台之一&#xff0c;其私域流量的价值不言而喻。那么&#xff0c;如何才能轻松玩转微信私域流量呢&#xff1f;接下来&#xff0c;我们将为你介绍一款强大的…

设计模式:抽象工厂模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)

大家好&#xff01;本节主要介绍设计模式中的抽象工厂模式。 简介&#xff1a; 抽象工厂模式&#xff0c;它是所有形态的工厂模式中最为抽象和最具一般性的一种形态。它用于处理当有多个抽象角色时的情况。抽象工厂模式可以向客户端提供一个接口&#xff0c;使客户端在不必指…

TCP/IP(十九)TCP 实战抓包分析(三)TCP 第一次握手 SYN 丢包

一 TCP 三次握手异常情况实战分析 说明&#xff1a; 本文是TCP 三次握手异常系列之一 ① 异常场景 接下里我用三个实验案例,带大家一起探究探究这三种异常关注&#xff1a; 如何刻意练习模拟上述场景 以及 wireshark现象 ② 实验环境 ③ 实验一&#xff1a;TCP 第一次握…

STM32F407在RAM中执行程序

STM32F407在flash中执行代码的速度比在ram中执行代码的速度快。因为STM32F407有一颗“自适应实时存储器加速器”&#xff0c;这里不讨论ART Accelerator的加速方案。 把代码放在RAM中执行纯粹是为了学习。 将个别函数的代码放到RAM中运行 使用自己编写的链接脚本(sct文件)。 …

《论文阅读28》OGMM

一、论文 研究领域&#xff1a; 点云配准 | 有监督 部分重叠论文&#xff1a;Overlap-guided Gaussian Mixture Models for Point Cloud Registration WACV 2023 二、概述 概率3D点云配准方法在克服噪声、异常值和密度变化方面表现出有竞争力的性能。本文将点云对的配准问题…

【计算机网络原理】初始网络基础

文章目录 1. 网络发展史1.1 单机时代1.2 网络互连局域网 LAN广域网 WAN 2. 网络通信基础2.1 IP 地址2.2 端口号2.3 协议2.4 五元组2.5 协议分层2.5.1 OSI七层模型2.5.2 TCP/IP五层模型 2.6 封装和分用2.6.1 数据封装(发送方情况)2.6.2 数据分用(接收方情况) 总结 1. 网络发展史…

这是不是你们都在找的免费又好用的配音网站?

随着人工智能技术的不断发展和普及&#xff0c;AI配音软件也越来越多地进入人们的视野。它可以帮助我们快速地将文字转换成语音&#xff0c;让我们的工作变得更加高效和便捷。在本文中&#xff0c;我将介绍一款非常实用而且免费的AI配音网站&#xff0c;超级简单好用&#xff0…

C++string的使用

CSDN的uu们&#xff0c;大家好。这里是C入门的第十六讲。 座右铭&#xff1a;前路坎坷&#xff0c;披荆斩棘&#xff0c;扶摇直上。 博客主页&#xff1a; 姬如祎 收录专栏&#xff1a;C专题 目录 1.构造函数 1.1 string() 1.2 string(const char* s) 1.3 string(const …

Cinema 4D云渲染一分钟动画要多少钱?如何进行Cinema 4D云渲染?看完就懂了

&#xfeff;1.为什么Cinema 4D要使用云渲染&#xff1f; 近年来&#xff0c;Cinema 4D在实现视觉效果方面取得了很大的进展。但是&#xff0c;随着视觉效果的复杂化&#xff0c;渲染的工作量也相应增加&#xff0c;导致渲染时间变长。在这种情况下&#xff0c;云渲染平台就能…

Linux嵌入式系统开发之路:从小白到大牛

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 嵌入式系统开发是一个充…

Spring framework Day22:Aware接口

前言 在Spring框架中&#xff0c;有许多接口和类都有一个非常重要的作用——让我们能够更方便地构建应用程序和管理组件。其中&#xff0c;Aware接口就是其中一个非常重要的接口之一。通过实现该接口&#xff0c;我们可以让Spring容器感知到特定的组件和资源&#xff0c;并进行…

媒体转码和输出软件:Media Encoder 2024中文版

想要高效地转码、优化输出吗&#xff1f;那就来尝试全新的Media Encoder 2024吧&#xff01;Media Encoder是Adobe公司出品的一款媒体转码和输出软件&#xff0c;可以帮助您快速、高效地将多种格式的视频和音频转换为所需的输出格式。 全新的Media Encoder 2024提供了更加智能…

【CANoe】XML Test Module使用实例

文章目录 一、实操步骤1、增加XML Test Module节点2、配置XML Test Module节点3、XML Test Module节点增加CAPL脚本(.can文件)4、文件夹结构5、使用仿真节点开始测试6、测试结果与测试报告7、同理&#xff0c;在Test Setup也可如此操作 一、实操步骤 1、增加XML Test Module节…

使用conda install一直卡在solving environment的解决方法

使用国内镜像源&#xff0c;但install仍旧一直卡在solving environment&#xff0c;超过10分钟就不用等了&#xff1b; 检查C:\Users\UserName 路径下的.condarc文件 将这个defaults这一行删掉即可

【Linux-常用命令-基础命令-复制-copy-命令-笔记】

【Linux-常用命令-基础命令-复制文件-copy-命令-笔记】 1、前言2、操作3、自己的实践 1、前言 最近&#xff0c;在使用Linux的时&#xff0c;使用相关基础命令是&#xff0c;总是容易忘记&#xff0c;上网一搜&#xff0c;大部分都写的比较繁琐&#xff0c;我就找下复制命令&a…

【算法设计与分析qwl】04 NP-hard——只是举例几个,货郎,双机调度,01背包

NP-hard问题&#xff1a; 有效算法是 输入规模的多项式时间算法。 这些问题的难度处于可有效计算的边界。 算法数据结构程序设计 例4 货郎问题 建模与算法&#xff1a; 解是一个排列&#xff0c; 0-1背包问题&#xff1a; 建模&#xff1a; 双机调度&#xff1a; 建模&#x…