C++泛型编码的理解

1.指针的算术运算

  假设我们要完成一下工作。给定一个储存整数的vector,以及一个整数值,如果此值存在于vector内,我们必须返回一个指针指向该值;反之则返回0,表示此值不在vector内。以下便是我的做法:

const int *find(const vector<int> &vec, int value)
{
   for (int i = 0; i < vec.size(); ++i)
   {
       if (vec[i] == value) 
           return &vec[i];
   }
   return 0;
}

  测试这个函数,发现其结果的确满足我们的需求,但是我们又获得一个新人物:想办法让这个函数不仅可以处理整数,更可以处理任何类型--前提是该类型定义有equality(相等)运算符。此时,我们可以运用function template的形式呈现:

template <typename elemType>
const elemType* find(const vector<elemType> &vec,
               const elemType &value)
{
    for (int i = 0; i < vec.size(); i++)
    {
        if (vec[i] == value)
            return &vec[i];
    }
    return 0;
}

  再次测试这个函数,其执行结果同样符合我们的需求。继续下一个任务,便是让这个函数同时可以处理vector与array内的任意类型元素--当然该类型的equality运算符依旧已定义。首先映入脑海的想法便是函数重载(overload),一份用来处理vector,另一份用来处理array。

//处理vector的版本
template <typename elemType>
const elemType* find(const vector<elemType> &vec,
               const elemType &value)
{
    for (int i = 0; i < vec.size(); i++)
    {
        if (vec[i] == value)
            return &vec[i];
    }
    return 0;
}

//处理array的版本
template <typename elemType, size_t n>
const elemType* find(const array<elemType, n> &arr,
                            const elemType &value)
{
    for (int i = 0; i < arr.size(); i++)
    {
        if (arr[i] == value)
            return &arr[i];
    }
    return 0;
}

  测试重载版本,发现其结果也同样满足我们的需求,但是重复编写两份逻辑类似的代码似乎有点多此一举。有一种存在已久的对策,就是将问题分割为数个较小、相对简单的子问题。本例中我们的大问题可以切割为:(1)将array的元素传入find(),而不指明该array,(2)将vector的元素传入find(),而非指明该vector。
  首先解决array的处理问题。如何才能够在不指定array的情形下将其元素传入find()呢?我们可以回想一下C语言中如何传参数组。当我们写下:
  int min(int array[24]) { ... }
  min()似乎仅能接受某个拥有24个元素的array,并且以值的方式传入。事实上,这两个假设都是错误的:array并不会以传值方式复制一份,而且我们可以传递任意大小的array给min()。
  当数组被传给函数,或是由函数中返回,仅有第一个元素的地址会被传递。一下的min()函数声明就精确多了:
  int min(int *array) { ... }
  min()可接受任意大小:1, 32, 1024, 等等,此时这迫使我们必须为不同大小的array编写其专属的min()函数。
  指向array开头的指针,使我们得以开始对array进行读取操作。接下来我们必须设法告诉min(),应该在何处停止对array的读取。解法之一是:增加一个参数,用来表示array的大小。如下:

template <typename elemType>
const elemType* find(const elemType *array, int size,
               const elemType &value)
{
    if (!array || size < 1)
        return nullptr;
    for(int i = 0; i < size; i++)
    {
        if (value == array[i])
           return &array[i];
    }
    return nullptr;
}

  解法之二则是传入另一个地址,指示array读取操作的重点。

template <typename elemType>
const elemType* find(const elemType *first, const elemType *last,
               const elemType &value)
{
    if (!first || !last)
        return 0;
    for (; first != last; ++first)
        if (*first == value)
            return first;
    return 0;
}

  这种解法使得array从参数列表中彻底消失了--解决了我们的前面提到的第一个小问题。

posted @ 2024-07-01 15:01  ydqun  阅读(4)  评论(0编辑  收藏  举报