跟踪返回类型 (C++11)

如果返回类型依赖于函数自变量的类型,那么尾部返回类型功能将除去 C++ 限制,其中无法对函数模板的返回类型进行泛化。 例如, ab 是函数模板 multiply(const A &a, const B &b)的自变量,其中 ab 是任意类型。 如果没有尾部返回类型功能,那么无法声明 multiply 函数模板的返回类型以泛化 a*b的所有观测值。 通过此功能,可以在函数自变量后指定返回类型。 当函数模板的返回类型取决于函数自变量的类型时,这将解决作用域限定问题。

尾部返回类型语法

读取语法图跳过可视语法图 function_identifier ( 参数声明 ) cv_qualifier_seq异常声明  -> 返回类型
备注信息:
  • 此语法不是函数声明或定义的语法。 自动占位符在其指定 return_type_说明符的声明和定义的语法中出现。
  • 与没有尾部返回类型的函数声明符一样,此语法可用于声明函数的指针或引用。
  • 可以使用 direct_声明者 的语法代替 function_identifier来构成更复杂的类型。 有关 direct_声明者的详细信息,请参阅 声明者概述

要使用尾部返回类型功能,请在函数标识之前使用 auto 关键字声明通用返回类型,并在函数标识之后指定准确的返回类型。 例如,使用 decltype 关键字来指定精确的返回类型。

在以下示例中, auto 关键字放在函数标识 add之前。 add 的返回类型为 decltype(a + b),这取决于函数自变量 ab的类型。
// Trailing return type is used to represent 
// a fully generic return type for a+b.
template <typename FirstType, typename SecondType> 
auto add(FirstType a, SecondType b) -> decltype(a + b){
   return a + b;
}

int main(){
   // The first template argument is of the integer type, and
   // the second template argument is of the character type.
   add(1, 'A'); 

   // Both the template arguments are of the integer type.
   add(3, 5); 
}
备注信息:
  • 使用尾部返回类型时,占位符返回类型必须为 auto。 例如,语句 auto *f()->char 会导致编译时错误,因为不允许使用 auto * 作为占位符返回类型。
  • auto 类型说明符可以与具有尾部返回类型的函数声明符配合使用。 否则,将根据自动类型扣除功能使用 auto 类型说明符。 有关自动类型扣除的更多信息,请参阅 自动类型说明符 (C++11)。 因为函数声明不能具有自动类型扣除所需的初始化方法,所以不能在没有尾部返回类型的函数声明中使用 auto 类型说明符。 对于对函数的指针和引用的声明,可以将 auto 类型说明符与相应的尾部返回类型或初始化方法配合使用。 有关指向函数的指针和引用的详细信息,请参阅 指向函数的指针
  • 函数的返回类型不能是以下任何类型:
    • 函数
    • 数组
    • 不完整的类
  • 函数的返回类型无法定义以下任何类型:
    • struct
    • class
    • union
    • enum
    但是,如果未在函数声明中定义类型,那么返回类型可以是这些类型中的任何类型。
此外,在函数具有复杂返回类型的情况下,此功能使您的程序更加紧凑和优雅。 如果没有此功能,那么程序可能很复杂且容易出错。 请参阅以下示例:
template <class A, class B> class K{
   public: 
      int i;
};

K<int, double> (*(*bar())())() {
   return 0;
}
您可以使用尾部返回类型功能来压缩代码。 请参阅以下示例:
template <class A, class B> class K{
   public: 
      int i;
};

auto bar()->auto(*)()->K<int, double>(*)(){
   return 0;
}
此功能还可用于类的成员函数。 在以下示例中,程序是简明的,因为在使用尾部返回类型之后,不需要限定成员函数 bar 的返回类型:
struct A{
   typedef int ret_type;
   auto bar() -> ret_type;
};

// ret_type is not qualified
auto A::bar() -> ret_type{  
   return 0;
}
此功能的另一个用途是编写完美的转发功能。 即,转发函数调用另一个函数,转发函数的返回类型与被调用函数的返回类型相同。 请参阅以下示例:
double number (int a){
   return double(a);
}

int number(double b){
   return int(b);
}

template <class A> 
auto wrapper(A a) -> decltype(number(a)){
   return number(a);
}

int main(){
   // The return value is 1.000000.
   wrapper(1); 

   // The return value is 1.
   wrapper(1.5); 
}
在此示例中, wrapper 函数和 number 函数具有相同的返回类型。