C ++ 14中的尾随返回类型

时间:2016-10-10 03:53:20

标签: c++ c++14 auto

在C ++ 14中引入auto返回类型,是否有任何实际情况需要尾随返回类型,或者它在C ++ 14和17中完全过时了?

3 个答案:

答案 0 :(得分:11)

考虑...

auto f(int x)
{
    if (x == 2)
        return 3;
    return 2.1;
}

...这有一个不明确的返回类型 - intdouble。显式返回类型 - 无论是前缀还是尾随 - 可以消除歧义,并将return参数强制转换为返回类型。

如果您想在某些参数上使用decltypesizeof等,

特别是尾随返回类型也很有用:

auto f(int x) -> decltype(g(x))
{
    if (x == 2)
        return g(x);
    return 2;
}

答案 1 :(得分:10)

尾随返回类型为您提供SFINAE支持。推迟返回类型永远不会导致错误,只是替换失败。

这允许编译器不必编译整个任意函数体,然后干净地退出以确定是否适用过载。

答案 2 :(得分:2)

除了您需要使用它(此处的其他答案提供了很好的示例)之外,您可以将其用于清晰度,以明确说明函数返回的内容。一旦你意识到(希望很快)阅读代码至少与编写代码一样重要,这一点非常重要。

考虑:

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);
}

Okey ......,现在让我们遵循:

auto split_impl(gsl::cstring_span str)
{
   return split_impl(str, ::isspace);
}

你是开玩笑吧。

所以我希望你明白这一点。

我并不是说总是使用显式返回类型,我说要考虑知道返回类型应该快速简单地看一下该函数。有时,对于单行,可以从身体中发现。有时,可以从名称中安全地猜到(例如is_empty()明确返回bool)。其他时候,您需要明确地命名它。让开发人员以后使用代码的生活更简单,特别是因为那个人最终不可避免地会成为你。