当前位置: 首页 > news >正文

C++11 之模板改进

模板的右尖括号

在 c++98/03 的泛型编程中,模板实例化有一个很烦琐的地方,那就是连续两个右尖括号(>>)会被编译器解释成右移操作符,而不是模板参数表的结束,所以需要中间加个空格进行分割,避免发生编译错误。

int main() {std::vector<std::vector<int>> a; // errorstd::vector<std::vector<int> > b; // ok
}

现在在 c++11 中,这种限制终于被取消了。在 c++11 标准中,要求编译器对模板的右尖括号做单独处理,使编译器能够正确判断出 >> 是一个右移操作符还是模板参数表的结束标记(delimiter,界定符)。

template <typename T>
struct Foo
{typedef T type;
};template <typename T>
class A
{// ...
};int main(void)
{Foo<A<int>>::type xx;  return 0;
}

模板的别名—using 定义别名

大家都知道,在 c++ 中可以通过 typedef 重定义一个类型,被重定义的类型并不是一个新的类型,仅仅只是原有的类型取了一个新的名字。但是使用 typedef 存在两个问题:

  • 对于复杂类型而言,使用 typedef 重定义相对繁琐;
  • typedef 的定义方法和变量的声明类似,这种写法凸显了 c/c++ 中的语法一致性,但有时却会增加代码的阅读难度;
  • typedef 无法重定义一个模板。

c++11 引入了 using,using 的别名语法覆盖了 typedef 的全部功能,可以轻松的定义别名而不是使用繁琐的 typedef。

typedef unsigned int uint_t;  // before c++11
using uint_t = unsigned int;  // c++11typedef std::vector<std::vector<int>> vvi; // before c++11
using vvi = std::vector<std::vector<int>>; // c++11

使用 using 明显简洁并且易读。

定义函数指针之类的操作:

typedef void (*func)(int, int); // 啥玩意,看不懂
using func = void (*)(int, int); // 起码比 typedef 容易看的懂吧

上面的代码使用 using 起码比 typedef 容易看的懂一些吧,但是我还是看不懂,因为我从来不用这种来表示函数指针,用 std::function()std::bind()std::placeholder()、lambda 表达式它不香吗。

函数模板的默认模板参数

c++11 之前只有类模板支持默认模板参数,函数模板是不支持默认模板参数的,c++11 后都支持。以下是 c++11 后支持的写法的示例:

// 类模板
template <typename T, typename U=int>
class A {T value;  
};template <typename T=int, typename U> // error
class A {T value;  
};

类模板的默认模板参数必须从右往左定义,即模板参数必须写在参数表的最后,而函数模板则没有这个限制。甚至于,根据实际场景中函数模板被调用的情形,编译器还可以自行推导出部分模板参数的类型。

// 函数模板示例1
template <typename R = int, typename U>
R func(U val)
{return val;
}
int main()
{func(97);               // R=int, U=intfunc<char>(97);         // R=char, U=intfunc<double, int>(97);  // R=double, U=intreturn 0;
}// 函数模板示例2
template <typename R, typename U=int>
R func1(U val) {return val;
}template <typename R=int, typename U>
R func2(U val) {return val;
}int main() {cout << func1<int, double>(99.9) << endl; // 99cout << func1<double, double>(99.9) << endl; // 99.9cout << func1<double>(99.9) << endl; // 99.9cout << func1<int>(99.9) << endl; // 99cout << func2<int, double>(99.9) << endl; // 99cout << func1<double, double>(99.9) << endl; // 99.9cout << func2<double>(99.9) << endl; // 99.9cout << func2<int>(99.9) << endl; // 99return 0;
}

总的来说,c++11 支持为函数模板中的参数设置默认值,在实际使用过程中,我们可以选择使用默认值,也可以尝试由编译器自行推导得到,还可以亲自指定各个模板参数的类型。

http://www.lryc.cn/news/16921.html

相关文章:

  • Linux - POSIX信号量,基于环形队列的生产者消费者模型
  • 学习Flask之七、大型应用架构
  • CentOS9下编译FFMPEG源码
  • 炼石:八年饮冰难凉热血,初心如磐百炼成钢
  • Python基本数据类型
  • 【MySQL进阶】 锁
  • javascript高级程序设计第四版读书笔记-第五章 基本引用类型
  • 《爆肝整理》保姆级系列教程python接口自动化(二十一)--unittest简介(详解)
  • 【C++的OpenCV】第四课-OpenCV图像常用操作(一):Mat对象深化学习、灰度、ROI
  • Propargyl-PEG1-SS-PEG1-PFP ester,1817735-30-0,炔基应用于生物标记
  • 产品运营︱用户活跃度低的解决方法
  • 【华为OD机试模拟题】用 C++ 实现 - 求最大数字
  • 吉卜力风格水彩画怎么画?
  • Python的类变量和对象变量声明解析
  • #笨鸟先飞 猴博士电路笔记 第一篇 电路基础
  • 快捷式~node.js环境搭建
  • ZooKeeper实现分布式队列、分布式锁和选举详解
  • 【swift】swift quick start
  • 浅谈volatile关键字
  • 10 种 Spring事务失效场景
  • 重读《DOOM启世录》
  • 巧用性格上的差异来组建团队
  • Leetcode11. 盛最多水的容器
  • Java笔记026-集合/数组、Collection接口、ArrayList、Vector、LinkedList
  • Hive学习——分桶抽样、侧视图与炸裂函数搭配、hive实现WordCount
  • 大数据算法
  • 非暴力沟通读书笔记
  • 代码随想录【Day21】| 530. 二叉搜索树的最小绝对差、501. 二叉搜索树中的众数、236. 二叉树的最近公共祖先
  • 注意啦,面试通过后,别忘了教师资格证认定
  • 【LeetCode】No.154. 寻找旋转排序数组中的最小值 II -- Java Version