欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > C++学习笔记----11、模块、头文件及各种主题(二)---- 函数模板(1)

C++学习笔记----11、模块、头文件及各种主题(二)---- 函数模板(1)

2025/6/24 14:02:05 来源:https://blog.csdn.net/weixin_71738303/article/details/143699730  浏览:    关键词:C++学习笔记----11、模块、头文件及各种主题(二)---- 函数模板(1)

        也可以为单独的函数写模板。语法与类模板类似。例如,可以写如下通用的函数来查找数组中的值并返回其索引:

template <typename T>
optional<size_t> Find(const T& value, const T* arr, size_t size)
{for (size_t i{ 0 }; i < size; ++i) {if (arr[i] == value) {return i; // Found it; return the index.}}return {}; // Failed to find it; return empty optional.
}

        Find函数模板可以用于任何类型的数组。例如,可以用其查找int数组中的int的索引或SpreadsheetCell数组中的SpreadsheetCell。

        可以用两种方式调用函数:用<>显式指定模板类型参数或省略类型让编译器从参数中推断类型参数。下面是例子:

int main()
{int myInt{ 3 }, intArray[]{ 1, 2, 3, 4 };const size_t sizeIntArray{ size(intArray) };optional<size_t> res;res = Find(myInt, intArray, sizeIntArray);        // calls Find<int> by deduction.res = Find<int>(myInt, intArray, sizeIntArray);   // calls Find<int> explicitly.if (res) { println("{}", *res); }else { println("Not found"); }double myDouble{ 5.6 }, doubleArray[]{ 1.2, 3.4, 5.7, 7.5 };const size_t sizeDoubleArray{ size(doubleArray) };res = Find(myDouble, doubleArray, sizeDoubleArray);         // calls Find<double> by deduction.res = Find<double>(myDouble, doubleArray, sizeDoubleArray); // calls Find<double> explicitly.if (res) { println("{}", *res); }else { println("Not found"); }//res = Find(myInt, doubleArray, sizeDoubleArray);        // DOES NOT COMPILE! Arguments are different types.res = Find<double>(myInt, doubleArray, sizeDoubleArray);  // calls Find<double> explicitly, even with myInt.SpreadsheetCell cell1{ 10 };SpreadsheetCell cellArray[]{ SpreadsheetCell{ 4 }, SpreadsheetCell{ 10 } };const size_t sizeCellArray{ size(cellArray) };res = Find(cell1, cellArray, sizeCellArray);                  // calls Find<SpreadsheetCell> by deduction.res = Find<SpreadsheetCell>(cell1, cellArray, sizeCellArray); // calls Find<SpreadsheetCell> explicitly.res = Find(myInt, intArray);
}

        上面的Find()函数的实现要求作为其中的一个参数给出数组的大小。有时编译器是知道数组的确切大小的,例如,对于基于堆的数组。不必要传递数组的大小就能够调用Find()会比较好。可以通过添加如下的函数模板来达到目的。其实现只是将前面的Find()函数模板进行了间接调用。也演示了函数模板可以使用无类型参数,就像类模板一样。

template <typename T, size_t N>
optional<size_t> Find(const T& value, const T(&arr)[N])
{return Find(value, arr, N);
}

Find()重载的语法看起来有一点儿奇怪,但是其用法是直接的,示例如下:

int myInt { 3 }, intArray[] {1, 2, 3, 4};
optional<size_t> res { Find(myInt, intArray) };

        与类模板成员函数定义类似,函数模板定义(不仅仅是原型)必须对使用它们的所有源文件可用。这样的话,应该将定义放到模块定义接口文件中,如果不只一个源文件使用它们的话要进行导出。

        最后,函数模板的模板参数可以有缺省省,与类模板类似。

        注意:C++是标准库提供了std::find()函数模板,比这里示例的Find()函数模板要强大得多。

1、函数重载与函数模板

        当要提供一个函数可以使用两种不同的数据类型时有两种选择:提供函数重载或提供函数模板。在这两种选项中怎么选择呢?

        当写一个函数用于不同的数据类型时,函数体对于所有数据类型都是一样的,就提供函数模板。如果函数体对于不同的数据类型是不同,就提供函数重载。

2、函数模板重载

        理论上,c++语言允许写函数模板特例,与写类模板特例一样。然而,很少会想这样做,因为这样的函数模板特例不参与重载解析,因此可能行为不可预知。

        反之,可以用非模板函数或其他函数模板来重载函数模板。例如,你可以想要写一个Find()来重载const char*的C风格的字符串来用strcmp()进行比较,而不是用operator==,因为==只会比较指针,而不是真正的字符串。下面是这样的一个重载:

template <typename T>
optional<size_t> Find(const T& value, const T* arr, size_t size)
{println("original");for (size_t i{ 0 }; i < size; ++i) {if (arr[i] == value) {return i; // Found it; return the index.}}return {}; // Failed to find it; return empty optional.
}

        重载的函数可以使用如下:

int main()
{// Using an array for word to make sure no literal pooling happens, see Chapter 2.const char word[]{ "two" };const char* words[]{ "one", "two", "three", "four" };const size_t sizeWords{ size(words) };optional<size_t> res{ Find(word, words, sizeWords) }; // Calls non-template find.if (res) { println("{}", *res); }else { println("Not found"); }res = Find<const char*>(word, words, sizeWords); // Calls template with T=const char*.if (res) { println("{}", *res); }else { println("Not found"); }
}

        对Find()的调用正确地找到了字符串”two”在索引1上。

        如果显式地指定了模板类型参数如下,那么 函数模板就会用T=const char*,而不是const char*的重载:

res = Find<const char*>(word, words, sizeWords);

        其对Find()的调用没有找到匹配的,因为它没有比较真正的字符串,而是比较的指针。

        当编译器的重载解析过程有两个可能的候选项时,一个是函数模板,另一个是非模板函数,那么 编译器总是倾向于使用非模板函数。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词