策略技术中的算法策略
- 在之前博客中
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,一切正常。