在 C++11 函数中使用尾随 return 类型的优点
Advantage of using trailing return type in C++11 functions
与普通的 return 类型相比,在 C++11 中指定尾随 return 类型有什么好处?在此处查看 foo1
与 foo2
:
int foo1() {
return 1;
}
auto foo2() -> int {
return 1;
}
int main() {
foo1();
foo2();
}
在此示例中,它们的意思完全相同。
但是,始终如一地使用尾部 return 类型形式有一些优点(Phil Nash 称这些为 "East End Functions",因为 return 类型位于东端)。
使用参数。显然,当使用参数来确定 return 类型时,您 必须 使用尾随 return 类型。
template <typename T>
auto print(T const& t) -> decltype(std::cout << t) { return std::cout << t; }
名称查询。在尾随 return 类型中,名称查找包括成员函数定义的 class 范围。这意味着如果你想 return 一个嵌套的 class:
,你不必重新输入 class
Type C::foo() { ... } // error: don't know what Type is
C::Type C::foo() { ... } // ok
auto C::foo() -> Type { ... } // ok
同样,为了定义成员函数,其中 class 名称出于某种原因必须在全局命名空间中消除歧义,并且 return 类型是 class:
D ::C::foo() { ... } // error, parsed as D::C::foo() { ... }
auto ::C::foo() -> D { ... } // ok
信息排序更加合理。假设您想编写一个函数 to_string
,它接受一个 int
和 return 一个 string
。这是一种非常明智的措辞方式。函数名称、参数、return 类型。你不会说你想写一个名为 to_string
的 string
-returning 函数接受一个 int
。这是一个尴尬的信息顺序。名称是最重要的,其次是参数,然后是 return 类型。尾随 return 类型的形式可以让您更好地对这些信息进行排序。
在某些情况下尾随-return-类型是强制性的,在某些情况下它是有帮助的,在某些情况下它做同样的事情。除了简单的字符数之外,没有其他原因导致更糟糕的情况。
此外,从数学上讲,我们习惯于将函数视为 A -> B
而不是 B(A)
,因此 auto(*)(A) -> B
是一个接受 A
的函数指针return B
比 B(*)(A)
.
更接近那个观点
另一方面,写 auto main() -> int
看起来很可笑。
但老实说,这主要是因为不熟悉。这本身并没有什么可笑的。如果有的话,有点不幸的是语言在这里使用 auto
作为声明函数的方式 - 不是因为它太长(即其他一些语言使用 fun
甚至 fn
) -但是因为它与 auto
的其他用途并没有真正的区别。如果换成func
,我觉得会更好(虽然现在改也没什么意义)
最终,这纯粹是基于意见。只需编写有效的代码。
与普通的 return 类型相比,在 C++11 中指定尾随 return 类型有什么好处?在此处查看 foo1
与 foo2
:
int foo1() {
return 1;
}
auto foo2() -> int {
return 1;
}
int main() {
foo1();
foo2();
}
在此示例中,它们的意思完全相同。
但是,始终如一地使用尾部 return 类型形式有一些优点(Phil Nash 称这些为 "East End Functions",因为 return 类型位于东端)。
使用参数。显然,当使用参数来确定 return 类型时,您 必须 使用尾随 return 类型。
template <typename T> auto print(T const& t) -> decltype(std::cout << t) { return std::cout << t; }
名称查询。在尾随 return 类型中,名称查找包括成员函数定义的 class 范围。这意味着如果你想 return 一个嵌套的 class:
,你不必重新输入 classType C::foo() { ... } // error: don't know what Type is C::Type C::foo() { ... } // ok auto C::foo() -> Type { ... } // ok
同样,为了定义成员函数,其中 class 名称出于某种原因必须在全局命名空间中消除歧义,并且 return 类型是 class:
D ::C::foo() { ... } // error, parsed as D::C::foo() { ... } auto ::C::foo() -> D { ... } // ok
信息排序更加合理。假设您想编写一个函数
to_string
,它接受一个int
和 return 一个string
。这是一种非常明智的措辞方式。函数名称、参数、return 类型。你不会说你想写一个名为to_string
的string
-returning 函数接受一个int
。这是一个尴尬的信息顺序。名称是最重要的,其次是参数,然后是 return 类型。尾随 return 类型的形式可以让您更好地对这些信息进行排序。
在某些情况下尾随-return-类型是强制性的,在某些情况下它是有帮助的,在某些情况下它做同样的事情。除了简单的字符数之外,没有其他原因导致更糟糕的情况。
此外,从数学上讲,我们习惯于将函数视为 A -> B
而不是 B(A)
,因此 auto(*)(A) -> B
是一个接受 A
的函数指针return B
比 B(*)(A)
.
另一方面,写 auto main() -> int
看起来很可笑。
但老实说,这主要是因为不熟悉。这本身并没有什么可笑的。如果有的话,有点不幸的是语言在这里使用 auto
作为声明函数的方式 - 不是因为它太长(即其他一些语言使用 fun
甚至 fn
) -但是因为它与 auto
的其他用途并没有真正的区别。如果换成func
,我觉得会更好(虽然现在改也没什么意义)
最终,这纯粹是基于意见。只需编写有效的代码。