c++ 14中的尾随返回类型
Trailing return type in C++14
随着c++ 14中auto
返回类型的引入,是否存在需要尾随返回类型或者在c++ 14和c++ 17中完全过时的实际情况?
考虑…
auto f(int x)
{
if (x == 2)
return 3;
return 2.1;
}
…它有一个模棱两可的返回类型——int
或double
。显式返回类型(无论是前缀还是结尾)可以消除它的歧义,并将return
参数强制转换为返回类型。
decltype
, sizeof
等,尾随返回类型也特别有用:
auto f(int x) -> decltype(g(x))
{
if (x == 2)
return g(x);
return 2;
}
尾随返回类型为您提供SFINAE支持。推导出的返回类型不会导致足够早的错误,而仅仅是替换失败。
这允许编译器不必编译整个任意函数体,然后干净地返回以确定是否应用了重载。
除了需要使用它的地方(这里的其他答案给出了很好的例子),您还可以将它用于清晰度,用于显式声明函数返回的内容。一旦你意识到(希望很快)读代码至少和写代码一样重要,这一点就非常重要了。
考虑:
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
)。其他时候,您需要显式地命名它。使以后使用您代码的开发人员的生活更简单,特别是因为那个开发人员最终将不可避免地是您。
相关文章:
- 如何获取std::result_of函数的返回类型
- 奇怪的结构&GCC&clang(void*返回类型)
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 为什么与常规GCC不同,即使有"学究性错误",MinGW-GCC也能容忍丢失的返回类型
- 在没有定义返回类型的函数中返回布尔值,并将结果保存在无错误的char编译中-为什么
- 特征::矩阵<双精度,1,3> 结构类型函数中的返回类型函数
- 函数作为模板参数,是否对返回类型强制约束
- C++中函数的向量返回类型引发错误
- 检查函数返回类型是否与STL容器类型值相同
- 为什么返回类型中需要typename?C++
- <Windows>为什么 std::thread::native_handle 返回类型为"long long unsigned int"的值,而不是 void*(又名 HANDLE)?
- 警告:在函数返回类型 [-Wignore 限定符] 时忽略类型限定符
- 为什么 c++(g++) 不允许模板返回类型和函数名称之间有空格?
- 为什么返回类型的'const'限定符对标有 __forceinline/内联的函数没有影响?
- 推导 std::vector::back() 的返回类型
- 在 c++ 中将函数返回类型指定为模板参数
- 使用 SWIG 更改生成的 CS 函数中的返回类型
- QtQuick - qml:28:错误:未知方法返回类型:自定义类型
- 基于返回类型的转换和过载扣除
- 当返回类型声明为 ListNode 时,我们是否可以返回 false<T>*