在 C++11 函数中使用尾随返回类型的优点

Advantage of using trailing return type in C++11 functions

本文关键字:返回类型 C++11 函数      更新时间:2023-10-16

与普通返回类型相比,在 C++11 中指定尾随返回类型有什么优势?看看这里的foo1foo2

int foo1() {
return 1;    
}
auto foo2() -> int {
return 1;    
}
int main() {
foo1();
foo2();
}

在这个例子中,它们的意思完全相同。

但是,始终如一地使用尾随返回类型形式有一些优点(Phil Nash 称这些为"东端函数",因为返回类型位于东端(。

  1. 使用参数。显然,在使用参数确定返回类型时,必须使用尾随返回类型。

    template <typename T>
    auto print(T const& t) -> decltype(std::cout << t) { return std::cout << t; }
    
  2. 名称查找。在尾随返回类型中,名称查找包括成员函数定义的类范围。这意味着,如果要返回嵌套类,则不必重新键入类:

    Type C::foo() { ... }         // error: don't know what Type is
    C::Type C::foo() { ... }      // ok
    auto C::foo() -> Type { ... } // ok
    
  3. 同样,对于定义成员函数,由于某种原因,类名必须消除歧义才能位于全局命名空间中,并且返回类型为类:

    D ::C::foo() { ... }         // error, parsed as D::C::foo() { ... }
    auto ::C::foo() -> D { ... } // ok
    
  4. 更合理的信息排序。假设您要编写一个函数to_string,该函数采用int并返回string。这是一种非常明智的措辞方式。函数名称、参数、返回类型。你不会说你想编写一个名为to_stringstring返回函数,它需要一个int。这是一个尴尬的信息顺序。名称是最重要的,后跟参数,后跟返回类型。尾随返回类型表单允许您更好地对这些信息进行排序。

在某些情况下,跟踪返回类型是强制性的,在某些情况下它是有帮助的,在某些情况下它执行相同的操作。除了字符数之外,没有其他原因会使情况更糟的情况。

另外,从数学上讲,我们习惯于将函数视为A -> B而不是B(A),因此auto(*)(A) -> B函数指针接受A并返回BB(*)(A)更接近该视图。


另一方面,写auto main() -> int看起来很荒谬。

但老实说,这主要是因为不熟悉。它本身并没有什么可笑的。如果有的话,有点不幸的是,语言在这里使用auto作为声明函数的一种方式 - 不是因为它太长(即其他一些语言使用fun甚至fn( - 而是因为它与auto的其他用途并没有真正的区别。如果它是func,我认为它会更好(尽管现在改变没有任何意义(。


归根结底,这纯粹是基于意见的。只需编写有效的代码即可。