C++14 auto关键字的改进

Share on:
300 Words | Read in about 2 Min | View times

Overview

C++11对auto关键字进行了重新定义,到了C++14又对auto关键字做了进一步的改进。从C++14开始,auto关键字可以用于函数返回值推导和lambda表达式参数列表的类型推导了。本节内容就围绕这两项改进详细展开。

本系列文章将包括以下领域:

本章其他内容请见 《现代C++》

《C++ auto关键字》这篇文章介绍过关于C++11的auto关键字特性的介绍。

函数返回值类型推导

基本用法

C++11是不允许将函数返回值类型声明为auto的,会导致编译失败:

 1#include <iostream>
 2
 3auto foo(int a) {
 4    return a;
 5}
 6
 7int main() {
 8    auto ret = foo(1);
 9    std::cout << "foo(1) = " << ret << std::endl;
10    return 0;
11}

使用C++11进行编译g++ -std=c++11 main.cpp -o main将产生以下错误:

1main.cpp:3:1: error: ‘foo’ function uses ‘auto’ type specifier without trailing return type
2    3 | auto foo(int a) {
3      | ^~~~
4main.cpp:3:1: note: deduced return type only available with ‘-std=c++14’ or ‘-std=gnu++14’

改用C++14进行编译g++ -std=c++14 main.cpp -o main就通过了。

auto返回值还可以用于模板的函数返回值推导中:

1template<typename T>
2auto foo(T t) { return t; }

注意事项

  • 返回值有多个分支,必须保证每个分支返回的类型可以进行隐式转化,否则编译失败
1auto foo(bool flag) {
2    return flag ? "hello" : 10; //error: operands to ‘?:’ have different types ‘const char*’ and ‘int’
3}
4
5auto bar(bool flag) {
6    return flag ? 3.14 : 10; //ok
7}
  • 不能返回初始化列表
1auto baz() {
2    return {1, 2, 3}; //error: returning initializer list
3}
  • 不能用于虚函数
1struct A {
2    virtual auto foo() { return 1; } //error: virtual function cannot have deduced return type
3};
  • 用于递归函数中时,至少有一个退出路径返回具体类型
1auto fabonaci(int n) {
2    if (1 == n || 2 == n)
3        return 1;
4    return fabonaci(n - 1) + fabonaci(n - 2);
5}

lambda表达式参数列表类型推导

《C++闭包》这篇文章中介绍了lambda表达式是作为闭包的一种实现方式。在C++11中lambda表达式的参数列表的类型是不能声明为auto的,必须使用具体类型来声明。而在C++14,lambda表达式的参数列表类型已经可以通过auto自动推导了:

1auto f = [](auto a) { return a; };
2std::cout << f(1) << std::endl; //auto推导为int
3std::cout << f(3.14) << std::endl; //auto推导为double
Prev Post: 『STL std::sort是什么样的排序?』
Next Post: 『C++14模板的改进』