广州C/C++培训
达内广州岗顶中心

18087159764

热门课程

C++14 SFINAE解引用迭代器

  • 时间:2017-02-06
  • 发布:广州C++培训
  • 来源:博客园

广州达内C++培训的老师这一期给大家讲C++14 SFINAE解引用迭代器。

原问题:编写函数f(r),若r为迭代器,则返回f(*r),否则返回r。

摘要:

问题:

什么是迭代器?

迭代器是c++中的一个概念,若类型It满足以下条件,则It为迭代器类型

可拷贝构造(CopyConstructible)

可拷贝赋值(CopyAssignable)

可析构(Destructibale)

左值It对象可交换(Swappable)

std::iterator_traits<It>含如下类型成员:value_type, difference_type, reference, pointer和iterator_category

对于It的左值r,如下表达式合法且具有指定含义:

*r返回值类型:unspecified前置条件:r可解引用

++r返回值类型:It &前置条件:r可自增

在后续实现中,将放宽迭代器的要求:对左值r,设若*r合法,则r有迭代器类型。意即:

编写函数f(r),若左值r可被解引用,返回f(*r),否则返回r。

问题分析:

f的返回值类型需要随实际参数的变化而改变。例如:若实际参数类型为int *,则返回值类型为int,若实际参数类型为int **,则返回值类型为int *。不同形参,不同返回值的同名函数声明可通过重载来实现。

由于迭代器有无限多种,也无法预知用户代码会传递哪些类型的迭代器,手动添加这些重载是不现实的。需要借助编译器来根据调用自动“生成”(模板实例化)这些函数重载。

结合以上两点,f的声明应为含一个模板类型参数的函数模板。在编译时,由编译器根据各调用的实际参数,来生成并调用实现对应功能的函数。

若类型T的左值可被解引用,则实例化函数模板(1)

template <class T>

auto f(T r) {

return f(*r);

}

否则实例化函数模板(2)

template <class T>

auto f(T r) {

return r;

}

问题:

如何使得两个模板“互斥”。

方案1:通过SFINAE。当表达式e(检验r是否可被解引用)为真时,启用函数模板1。否则启用函数模板2

方案2:通过SFINAE。当表达式e(检验r是否可被解引用)为真时,启用函数模板1。而函数模板2总是可用,但其重载匹配的优先级低于由函数模板1(模板1的调用为Exact match,模板2的调用需要Conversion)

实现(方案2):

1 #include <cassert>

2

3 #include <type_traits>

4 #include <utility>

5

6 template <class T>

7 auto f(T x, ...) {

8  return x;

9 }

10

11 template <class T, class = decltype(*std::declval<T>())>

12 auto f(T x, int) {

13  return f(*x, 0);

14 }

15

16 int main() {

17  int x = 3, *p = &x;

18  assert(f(&p, 0)==3);

19  

20  return 0;

21 }

了解详情请登陆广州达内C++培训官网(gz.c.tedu.cn)!

上一篇:C++头文件系列
下一篇:二逼平衡树树状数组套主席树

2017下半年刷手机乘地铁一波来袭!【广州达内】

高频传输每秒 50GB,够劲!【达内c++培训】

程序员培训哪里好?达内让你一分钟搞定编程接口回调

广州C++培训:C语言学到什么程度可以做项目?

选择城市和中心
贵州省

广西省

海南省

台湾