简体   繁体   中英

Trailing return type in C++14

随着 C++14 中auto返回类型的引入,是否存在需要尾随返回类型或在 C++14 和 17 中完全过时的真实情况?

Consider...

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

...this has an ambiguous return type - int or double . An explicit return type - whether prefixed or trailing - can disambiguate it and casts the return argument to the return type.

Trailing return types specifically are also useful if you want to use decltype , sizeof etc on some arguments:

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

Trailing return type gives you SFINAE support. Deduced return types never cause an error early enough to be a mere substitution failure.

This permits compilers not to have to be able to compile entire arbitrary functions bodies and then back out cleanly in order to determine if an overload applies.

Apart from where you are required to use it (and the other answers here give great examples), you can use it for clarity , for explicitly stating what the function returns. This is very important once you realize (hopefully pretty soon) that reading a code is at least as important as writing it.

consider:

auto split(gsl::cstring_span str)
{
    ...
    ...
    auto tokens = std::vector<gsl::cstring_span>();
    ...
    ...
    for (...) {
        ...
        ...
        ...
    }
    ...
    return tokens;
}

versus:

auto split(gsl::cstring_span str) -> std::vector<gsl::cstring_span>();
{
   ... doesn't even matter
}

I shouldn't be looking in the implementation to see what the contract of the function is. I could probably guess what the return type is by looking at the first example, but these kind of assumptions are dangerous in programming. I would have to scan the implementation to be sure of what I receive when I call the function. With the second example, I have the interface cleanly stated. I don't care of the implementation, as the name is self-explanatory and so I don't have to look in the definition at all.

Further more consider this even worst example. Lets find out what this function returns:

auto split(const char* str)
{
   return split(gsl::cstring_span(str));
}

Ok, now search for that overload:

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

Okey..., now lets follow that:

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

Are you f** kidding me.

So I hope you see the point.

I am not saying always use explicit return type, I am saying consider that knowing the return type should be quickly with a simple glance at the function. Sometimes, for one-liners, that can be discovered from the body. Sometimes, it can be safely guessed from the name (eg is_empty() clearly returns bool ). Other times, you would need to explicitly name it. Make the developer's life who uses your code later simpler, especially since that one will eventually inevitably be you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM