随着auto返回类型在C++14中的引入,是否真的需要跟踪返回类型,或者在C++14和17中它已经完全过时了?
发布于 2016-10-10 06:07:11
想想..。
auto f(int x)
{
if (x == 2)
return 3;
return 2.1;
}...this有一个模糊的返回类型-- int或double。显式返回类型(无论是前缀还是后缀)可以消除它的歧义,并将return参数转换为返回类型。
如果您想在某些参数上使用decltype、sizeof等,特别是尾随返回类型也很有用:
auto f(int x) -> decltype(g(x))
{
if (x == 2)
return g(x);
return 2;
}发布于 2016-10-10 04:06:42
跟踪返回类型为您提供SFINAE支持。推导出的返回类型永远不会过早地导致错误,以致于仅仅是替换失败。
这允许编译器不必编译整个任意函数体,然后清清楚楚地退出,以确定是否存在重载。
发布于 2016-10-10 13:07:40
除了需要在哪里使用它(这里的其他答案给出了很好的例子),您还可以使用它来明确说明函数返回的。一旦您意识到(希望很快)阅读代码至少与编写代码一样重要,这一点非常重要。
考虑:
auto split(gsl::cstring_span str)
{
...
...
auto tokens = std::vector<gsl::cstring_span>();
...
...
for (...) {
...
...
...
}
...
return tokens;
}相对于:
auto split(gsl::cstring_span str) -> std::vector<gsl::cstring_span>();
{
... doesn't even matter
}我不应该在实现中查看函数的契约。通过查看第一个示例,我可能可以猜到返回类型是什么,但是这种假设在编程中是危险的。当我调用函数时,我必须扫描实现,以确定我收到了什么。在第二个例子中,我清楚地说明了接口。我不关心实现,因为名称是不言自明的,所以我根本不需要查看定义。
此外,考虑一下这个甚至是最坏的例子。让我们看看这个函数返回的是什么:
auto split(const char* str)
{
return split(gsl::cstring_span(str));
}好的,现在搜索重载:
auto split(gsl::cstring_span str)
{
return split_impl(str);
}好吧.现在让我们跟着:
auto split_impl(gsl::cstring_span str)
{
return split_impl(str, ::isspace);
}你在跟我开玩笑吗。
所以我希望你明白重点。
我并不是说总是使用显式返回类型,而是想知道返回类型应该很快,只需简单地浏览一下函数。有时,对于一行人来说,可以从身体中发现。有时,可以从名称中安全地猜测(例如,is_empty()显然返回bool)。其他时候,您需要显式地命名它。使以后使用您的代码的开发人员的生活更简单,特别是因为最终您将不可避免地成为开发人员。
https://stackoverflow.com/questions/39951084
复制相似问题