C++11 之模板改进

模板的右尖括号

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

int main() {
   std::vector<std::vector<int>> a; // error
   std::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++11

typedef 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=int
    func<char>(97);         // R=char, U=int
    func<double, int>(97);  // R=double, U=int
    return 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; // 99
   cout << func1<double, double>(99.9) << endl; // 99.9
   cout << func1<double>(99.9) << endl; // 99.9
   cout << func1<int>(99.9) << endl; // 99
   cout << func2<int, double>(99.9) << endl; // 99
   cout << func1<double, double>(99.9) << endl; // 99.9
   cout << func2<double>(99.9) << endl; // 99.9
   cout << func2<int>(99.9) << endl; // 99
   return 0;
}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值