目录
萃取技术中的value traits(值萃取)
一个常规范例
判断是否是void类型的一个范例
判断两个类型是否相同
萃取技术中的value traits(值萃取)
- 固定萃取:给进来一个类型,萃取出一个类型
- 值萃取核心思想:给进来一个类型,萃取出一个值
一个常规范例
【引例】//fixed traits类模板的泛化版本 template<typename T> struct SumFixedTraits; //不需要实现代码,因为不需要用该版本进行实例化。 //各个fixed traits类模板的特化版本 //(1)给进来char类型时,返回的是int类型 template <> struct SumFixedTraits<char> //char表示给进来的是char类型 { using sumT = int; //类型别名sumT代表int类型(返回类型) }; //(2)给进来int类型时,返回的是__int64(long long/int64_t)类型 template <> struct SumFixedTraits<int> //int表示给进来的是int类型 { using sumT = __int64; //类型别名sumT代表__int64类型(返回类型) }; //(3)....其他给进来的是某个类型,返回的是另外一个类型,可以任意扩展出多个SumFixedTraits类模板的特化版本。 //----------------------- template <typename T> auto funcsum(const T* begin, const T* end) { using sumT = typename SumFixedTraits<T>::sumT; //给进来一个类型(T),返回一个类型(sumT),这是fixed traits的运用。 sumT sum{}; for (;;) { sum += (*begin); if (begin == end) break; ++begin; } return sum; }
- 调用
int myintarray1[] = { 10,15,20 }; int myintarray2[] = { 1000000000,1500000000,2000000000 }; //10亿,15亿,20亿 char mychararray[] = "abc";//97,98,99 cout << funcsum(&myintarray1[0], &myintarray1[2]) << endl; //int funcsum<int>(const int*,const int*); cout << funcsum(&myintarray2[0], &myintarray2[2]) << endl; cout << (int)(funcsum(&mychararray[0], &mychararray[2])) << endl; //char funcsum<char>(const char*,const char*);
【给进一个类型,萃取出一个值】
- 输出
【增加double类型】//fixed traits类模板的泛化版本 template<typename T> struct SumFixedTraits; //(1)给进来char类型时,返回的是int类型 template <> struct SumFixedTraits<char> //char表示给进来的是char类型 { using sumT = int; //类型别名sumT代表int类型(返回类型) static const sumT initValue = 0; }; //(2)给进来int类型时,返回的是__int64(long long/int64_t)类型 template <> struct SumFixedTraits<int> //int表示给进来的是int类型 { using sumT = __int64; //类型别名sumT代表__int64类型(返回类型) static const sumT initValue = 0; }; //(3)....其他给进来的是某个类型,返回的是另外一个类型,可以任意扩展出多个SumFixedTraits类模板的特化版本。 template <typename T> auto funcsum(const T* begin, const T* end) { using sumT = typename SumFixedTraits<T>::sumT; //给进来一个类型(T),返回一个类型(sumT),这是fixed traits的运用。 //sumT sum{}; //零初始化 sumT sum = SumFixedTraits<T>::initValue; //给进来一个类型T,返回一个值,这就是value traits的运用。 for (;;) { sum += (*begin); if (begin == end) break; ++begin; } return sum; }
- 如果增加double模板
template<> struct SumFixedTraits<double> { using sumT = double; static const sumT initValue = 0.0; };
【增加double类型改进】
- 报错:
- error C2864: SumFixedTraits<double>::initValue:带有类内初始化表达式的静态数据成员必须具有不可变的常里整型类型,或必须被指定为"内联"
【增加类类型】template<> struct SumFixedTraits<double> { using sumT = double; static constexpr sumT initValue = 0.0; };
class A { public: A(int v1, int v2) :m_i(v1 + v2) {} //构造函数 int m_i; //成员变量 } template<> struct SumFixedTraits<A> { using sumT = A; static const sumT initValue{ 0,0 }; };
【增加类类型改进】
- 报错:带有类内初始化表达式的静态数据成员必须具有不可变的常里整型类型,或必须被指定为"内联"
【C++17引入内联变量】template<> struct SumFixedTraits<A> { using sumT = A; static const sumT initValue; //这是声明,不是定义 } A const SumFixedTraits<A>::initValue = A{ 0,0 }; //定义并初始化
【使用静态成员函数进行初始化】template<> struct SumFixedTraits<A> { using sumT = A; inline static const sumT initValue{ 0,0 }; }
【总结数组元素类型是类类型时初始化initValue的方法】template<> struct SumFixedTraits<A> { using sumT = A; static sumT initValue() { return sumT{ 0,0 }; } };
【所有类型都使用静态成员函数进行初始化】
- 在针对类A特化的SumFixedTraits类模板中只对initValue进行声明,然后在某个.cpp源文件中对initValue进行定义和初始化。
- 采用C++17引入的inline变量的解决方式,直接在针对类A特化的SumFixedTraits类模板中解决问题。
- 在SumFixedTraits的特化版本中引入静态成员函数initValue(inline)的方式来解决问题。
【重载类+=运算符】template<typename T> struct SumFixedTraits; template<> struct SumFixedTraits<char> { using sumT = int; static sumT initValue() { return 0; } }; template<> struct SumFixedTraits<int> { using sumT = __int64; static sumT initValue() { return 0; } }; template<> struct SumFixedTraits<double> { using sumT = double; static sumT initValue() { return 0.0; } }; template<> struct SumFixedTraits<A> { using sumT = A; static sumT initValue() { return sumT{ 0,0 }; } }; template<typename T> auto funcsum(const T* begin, const T* end) { using sumT = typename SumFixedTraits<T>::sumT; sumT sum = SumFixedTraits<T>::initValue(); for (;;) { sum += (*begin); if (begin == end) break; ++begin; } return sum; }
class A { public: A(int v1, int v2) :m_i(v1 + v2) {} //构造函数 int m_i; //成员变量 public: A& operator+=(const A& obj) { m_i += obj.m_i; return *this; } };
double mydblarray1[] = {12.8,15.8,20.6}; cout << funcsum(&mydblarray1[0], &mydblarray1[2]) << endl; A myaobjarray1[] = { A{2,3}, A{6,8},A{11,12} }; cout << funcsum(&myaobjarray1[0], &myaobjarray1[2]).m_i << endl;
- 输出
判断是否是void类型的一个范例
- is_void类模板:判断某个类型是否是void类型。
cout << "int是void类型吗?" << std::is_void<int>::value << endl; //0 cout << "void是void类型吗?" << std::is_void<void>::value << endl; //1
【is_void功能实现】
- 输出
template <typename T> struct voidValueTraits { static const bool value = false; }; template <> //特化版本 struct voidValueTraits<void> { static const bool value = true; };
- 调用
cout << "int是void类型吗?" << voidValueTraits<int>::value << endl; //0 cout << "void是void类型吗?" << voidValueTraits<void>::value << endl; //1
- 输出
判断两个类型是否相同
【is_same功能实现】
- is_same类模板,用于判断两个类型是否相同。
//泛化版本 template<typename T1, typename T2> struct IsSameType { static const bool value = false; }; //特化版本 template<typename T1> struct IsSameType<T1, T1> { static const bool value = true; };
- 调用
【使用变量模板改进写法】cout << IsSameType<int, const int>::value << endl; //0 cout << IsSameType<int, int>::value << endl; //1
//泛化版本 template<typename T1, typename T2> struct IsSameType { static const bool value = false; }; //特化版本 template<typename T1> struct IsSameType<T1, T1> { static const bool value = true; }; //变量模板 template<typename T1, typename T2> const bool IsSame_v = IsSameType<T1, T2>::value;
- 调用
【使用std::true_type/std::false_type优化写法】cout << IsSame_v<int, const int> << endl; //0 cout << IsSame_v<int, int> << endl; //1
//泛化版本 template<typename T1, typename T2> struct IsSameType : std::false_type { }; //特化版本 template<typename T1> struct IsSameType<T1, T1>:std::true_type { }; //变量模板 template<typename T1, typename T2> const bool IsSame_v = IsSameType<T1, T2>::value;