策略技术中的算法策略
- 在之前博客中
funcsum()函数模板
中,实现了对数组元素的求和运算。求和在这里可以看作一种算法,扩展一下思路,对数组元素求差、求乘积、求最大值和最小值等,都可以看作算法。 - 而当前的
funcsum()函数模板
中,已经将数组元素的求和算法固定写在了程序代码中,为了灵活地将求和算法调整为求乘积、求最大值等算法,可以通过引入一个策略(policy)类SumPolicy
达到目的。
// 求和策略类以实现求和算法
struct SumPolicy
{// 静态成员函数模板template<typename sumT,typename T> // sumT是和值类型,T是数组元素类型static void algorithm(sumT& sum, const T& value) // 该策略类的核心算法{sum += value;}
};
接着,为funcsum()函数模板
增加一个新的类型模板参数,这个模板参数的默认值就是这个策略类。
修改funcsum()函数模板
:
template<typename T,typename U = SumFixedTraits<T>,typename V = SumPolicy>
auto funcsum(const T* begin, const T* end)
{typename U::sumT sum = U::initValue();for (;;){// sum += (*begin); 此行被下面一行取代V::algorithm(sum, *begin);if (begin == end)break;++begin;}return sum;
}
如果要计算一个整型数组中元素的最小值,如何实现?第1件想到的事情就是写一个新的策略类,如这里写一个MinPolicy类
(仿照SumPolicy类
的写法)。
struct MinPolicy
{template<typename minT,typename T>static void algorithm(minT& min, const T& value){if (min > value)min = value;}
};
在main()
主函数中重新写入代码:
#include "killCmake.h"#include<string>using namespace std;template<typename T>
struct SumFixedTraits;template<>
struct SumFixedTraits<char>
{using sumT = int;static sumT initValue() {return 0;}
};// 最求值策略技术时,为了求最小值,初始化需要很大
// 所以初始值可以为int最大值21亿
template<>
struct SumFixedTraits<int>
{using sumT = __int64;static sumT initValue() {return 2100000000;}
};template<>
struct SumFixedTraits<double>
{using sumT = double;static sumT initValue() {return 0.0;}
};template<typename T,typename U = SumFixedTraits<T>>
auto funcsum(const T* begin, const T* end)
{// using sumT = typename SumFixedTraits<T>::sumT; 本行不需要// sumT sum = SumFixedTraits<T>::initValue(); 本行不需要typename U::sumT sum = U::initValue();for (;;){sum += (*begin);if (begin == end)break;++begin;}return sum;
}// 求和策略类以实现求和算法
struct SumPolicy
{// 静态成员函数模板template<typename sumT,typename T> // sumT是和值类型,T是数组元素类型static void algorithm(sumT& sum, const T& value) // 该策略类的核心算法{sum += value;}
};template<typename T,typename U = SumFixedTraits<T>,typename V = SumPolicy>
auto funcsum(const T* begin, const T* end)
{typename U::sumT sum = U::initValue();for (;;){// sum += (*begin); 此行被下面一行取代V::algorithm(sum, *begin);if (begin == end)break;++begin;}return sum;
}struct MinPolicy
{template<typename minT,typename T>static void algorithm(minT& min, const T& value){if (min > value)min = value;}
};int main()
{//char my_char_array[] = "abc";//std::cout << (int)(funcsum(&my_char_array[0], &my_char_array[2])) << std::endl;//std::cout << (int)(funcsum<char, SumFixedTraits<int>>(&my_char_array[0], &my_char_array[2])) << std::endl;int my_int_array1[] = { 10,15,20 };std::cout << funcsum<int, SumFixedTraits<int>, MinPolicy>(&my_int_array1[0], &my_int_array1[2]) << std::endl;return 0;
}
这个程序真的很经典,个人觉得,应该属于中上乘武功了
- 运行程序,看一看新增的代码结果是否正确,最开始发现结果为0,显然这个结果是不正确的。究其原因,在
funcsum()
中,sum
(用于保存数组元素最小值的变量)的初值被设置为0。如果是计算数组元素和值,则sum
的初值被设置为0是很正常的;但如果要计算数组元素的最小值,则把sum
的初值设置为0是不正常的(因为数组中元素的最小值也很可能比0大,有这个0存在,就无法找到数组中元素的真正最小值)。 - 解决方案有以下两个。
- (1)可以给
funcsum()函数模板
增加一个非类型模板参数,用于把初值传递进来。 - (2)也可以重新写一个固定萃取类模板取代当前的
SumFixedTraits模板
。这里采用后一种解决方案,书写一个新的固定萃取类模板,取名为MinFixedTraits
。
#include "killCmake.h"#include<string>using namespace std;template<typename T>
struct SumFixedTraits;template<>
struct SumFixedTraits<char>
{using sumT = int;static sumT initValue() {return 0;}
};// 最求值策略技术时,为了求最小值,初始化需要很大
// 所以初始值可以为int最大值21亿
template<>
struct SumFixedTraits<int>
{using sumT = __int64;static sumT initValue() {return 2100000000;}
};template<>
struct SumFixedTraits<double>
{using sumT = double;static sumT initValue() {return 0.0;}
};template<typename T>
struct MinFixedTraits;template<>
struct MinFixedTraits<int>
{// 求最小值,结果类型与元素类型相同即可// 为名字统一,都用sumT这个名字using sumT = int;static sumT initValue(){// 这里给整型最大值,相信任何一个数组元素都不会比这个值更大// 因此可以顺利找到数组元素中的最小值return INT_MAX;}
};// 求和策略类以实现求和算法
struct SumPolicy
{// 静态成员函数模板template<typename sumT,typename T> // sumT是和值类型,T是数组元素类型static void algorithm(sumT& sum, const T& value) // 该策略类的核心算法{sum += value;}
};template<typename T,typename U = SumFixedTraits<T>,typename V = SumPolicy>
auto funcsum(const T* begin, const T* end)
{typename U::sumT sum = U::initValue();for (;;){// sum += (*begin); 此行被下面一行取代V::algorithm(sum, *begin);if (begin == end)break;++begin;}return sum;
}struct MinPolicy
{template<typename minT,typename T>static void algorithm(minT& min, const T& value){if (min > value)min = value;}
};int main()
{int my_int_array1[] = { 10,15,20 };std::cout << funcsum<int, MinFixedTraits<int>, MinPolicy>(& my_int_array1[0], & my_int_array1[2]) << std::endl;return 0;
}
运行程序,新增的代码行结果为10,一切正常。