刚学习C++,对它的理解还停留在数据成员和成员函数,这里遇到的函数模板问题,解决不了
The function template min_elem() finds the smallest element in the range [first, last) and returns the iterator to the smallest element. The way how smallest is understood can be customized.
#include <functional>
#include <iostream>
#include <iterator>
#include <string>
#include <list>
#include <vector>
template<class ForwardIt, class Compare>
ForwardIt min_elem(ForwardIt first, ForwardIt last,
comp)
{
if (first == last)
return
;
ForwardIt smallest = first++;
for (;
; ++first) {
if (comp(*first, *smallest)) {
smallest = first;
}
}
return
;
}
template<class ForwardIt>
ForwardIt min_elem(ForwardIt first, ForwardIt last)
{
return min_elem(first, last, std::less<
std::iterator_traits<ForwardIt>::value_type>());
}
struct Student {
int id;
std::string name;
bool
(const Student& s2) const {
return id < s2.id;
}
};
std::ostream& operator<<(std::ostream& out, const Student& s)
{
out << s.name << s.id;
return out;
}
int main()
{
std::vector<int> v = { 3, 1, 4, 2, 5, 9 };
std::cout << "min element is: " << *min_elem(std::begin(v), std::end(v)) << std::endl;
std::list<double> l = { 3.1, 1.2, 4.3, 2.4, 5.5, 9.7 };
std::cout << "min element is: " << *min_elem(std::begin(l), std::end(l), std::greater<double>()) << std::endl;
Student s[] = { {30, "Curry"}, {23, "Lebron"}, {35, "Durant"} };
std::cout << "min element is: " << *min_elem(std::begin(s), std::end(s)) << std::endl;
}
还不太明白函数模板的原理
希望给出题目解答的同时,给出一些思路上的指点
// The function template min_elem() finds the smallest element in the range [first, last) and returns the iterator to the smallest element. The way how smallest is understood can be customized.
#include <functional>
#include <iostream>
#include <iterator>
#include <string>
#include <list>
#include <vector>
template<class ForwardIt, class Compare>
ForwardIt min_elem(ForwardIt first, ForwardIt last,
Compare // 比较类实例
comp)
{
if (first == last)
return first; // 返回第一个.
ForwardIt smallest = first++;
for (; first != last // 当前不是迭代器末尾.
; ++first) {
if (comp(*first, *smallest)) {
smallest = first;
}
}
return smallest // smallest保存着最小值。
;
}
template<class ForwardIt>
ForwardIt min_elem(ForwardIt first, ForwardIt last)
{
return min_elem(first, last, std::less< typename // 去除语义二义性。
std::iterator_traits<ForwardIt>::value_type>());
}
struct Student {
int id;
std::string name;
bool operator< //运算符重载
(const Student& s2) const {
return id < s2.id;
}
};
std::ostream& operator<<(std::ostream& out, const Student& s)
{
out << s.name << s.id;
return out;
}
int main()
{
std::vector<int> v = { 3, 1, 4, 2, 5, 9 };
std::cout << "min element is: " << *min_elem(std::begin(v), std::end(v)) << std::endl;
std::list<double> l = { 3.1, 1.2, 4.3, 2.4, 5.5, 9.7 };
std::cout << "min element is: " << *min_elem(std::begin(l), std::end(l), std::greater<double>()) << std::endl;
Student s[] = { {30, "Curry"}, {23, "Lebron"}, {35, "Durant"} };
std::cout << "min element is: " << *min_elem(std::begin(s), std::end(s)) << std::endl;
}
//The function template min_elem() finds the smallest element in the range[first, last) and returns the iterator to the smallest element.The way how smallest is understood can be customized.
#include <functional>
#include <iostream>
#include <iterator>
#include <string>
#include <list>
#include <vector>
template<class ForwardIt, class Compare>
ForwardIt min_elem(ForwardIt first, ForwardIt last,Compare comp) //comp是一个比较函数
{
//这里是只有一个元素的情况
if (first == last)
return first;
//这里就是一个循环找最小的元素,smallest保存最小元素的迭代器
ForwardIt smallest = first++;
//终止条件就是头迭代器到尾迭代器,说明整个走完了
for (;first!=last; ++first) {
if (comp(*first, *smallest)) {
smallest = first;
}
}
//返回迭代器
return smallest;
}
template<class ForwardIt>
ForwardIt min_elem(ForwardIt first, ForwardIt last)
{
//默认的一个从小到大的比较函数,传入的值是数据类型
return min_elem(first, last, std::less<std::iterator_traits<ForwardIt>::value_type>());
}
struct Student {
int id;
std::string name;
//重载<运算符
bool operator <(const Student& s2) const {
return id < s2.id;
}
};
std::ostream& operator<<(std::ostream& out, const Student& s)
{
out << s.name << s.id;
return out;
}
int main()
{
std::vector<int> v = { 3, 1, 4, 2, 5, 9 };
std::cout << "min element is: " << *min_elem(std::begin(v), std::end(v)) << std::endl;
std::list<double> l = { 3.1, 1.2, 4.3, 2.4, 5.5, 9.7 };
std::cout << "min element is: " << *min_elem(std::begin(l), std::end(l), std::greater<double>()) << std::endl;
Student s[] = { {30, "Curry"}, {23, "Lebron"}, {35, "Durant"} };
std::cout << "min element is: " << *min_elem(std::begin(s), std::end(s)) << std::endl;
}
首先 注意区分两个概念:
类模版 和模版类
函数模版 和 模版函数
类/函数模版 是家族 ,模版类/函数 是家族的一个成员。
C++中类模板的声明格式为template<模板形参表声明><类声明>,并且类模板的成员函数都是模板函数
什么是非类型模版參数:就是传来的参数 可以当作实參使用。
注意:
浮点数、类对象以及字符串是不允许作为非类型模板参数的。
非类型的模板参数必须在编译期就能确认结果。
模板的特性
首先来看一个例子:
template int Func1() { return n; }
int Func2(int n) { return n; }
你能看出这两个函数的区别在哪里吗?
它们的区别就在于,Func1的参数是编译期指定,如Func1<0>() ;而Func2的参数则是运行期指定。
一:分离编译
简单说什么是分离编译: 类似于项目中 编译生成 不同的链接文件的意思。
特性一:: 这正体现了模板的特性或者说是它的技术核心,就是编译期的动态机制,这种机制使程序在运行期具有更大的效率优势。
到此你是不是对本文开头那段代码有了更深入的理解了呢?
二 特化
特划分为 : 全特化 、半特化
半特化可以只是简单的特化 ,也可以说对类型的限制。 外部传T 等,内部用 *T & T 等。
特性 二: 如果一个模板没有被特化,那么编译器根本不会去理会它,也就是说模板内的代码被隐藏了
函数模板与类模板
函数模版
------后边跟着一个具体的函数
1
这是一个函数模板:template Func(T param) {}
函数模板的模板参数是隐式的,编译器会自动根据传入值的类型来确定模板参数的类型。因此函数模板的模板参数不能有默认值。
这是一个类模板:template class MyClass {};
类模板
------后边跟着一个具体的类
1
类模版的模板参数是显式的,使用一个模板类时必须指明其模板参数,因此类模板的模板参数可以有默认值。
我们还可以做更多的事情,比如MyClass可以派生自T(XTP界面库就是这么做的),在MyClass内部可以使用关于T的enum、typedef等等。这些将在下文一一谈到。
(我在这里提出一个建议,创建一个类模板,请记得第一件事就是对模板参数进行typedef定义。)
模板的部分特化与应用
模板最有价值的地方就是它的部分特化,也是应用最广泛的特性。
所谓“部分特化”也就是说,一个模板有多个参数,但我们只对其中一部分参数进行特化,或者是只针对常量模板参数的某种情况进行特化。
编译期ASSERT
这是对bool型模板参数部分特化的一个例子。最简单的实现:
template struct CompileTimeAssert;
template<> struct CompileTimeAssert {};
当我们将一个表达式作为模板参数,而这个表达式的值为false时,编译器就找不到合适的实现,便会报错了
事实是编译期可用的表达式或函数(如sizeof)数量上并不多。
模板总结 【优点】
【优点】
模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
增强了代码的灵活性
【缺陷】
3. 模板会导致代码膨胀问题,也会导致编译时间变长
4. 出现模板编译错误时,错误信息非常凌乱,不易定位错误