简体   繁体   中英

std::pair<auto, auto> return type

I was playing around with auto in std::pair . In the below code, function f is supposed to return a std::pair of types which depend on a template parameter.

A working example:

EXAMPLE 1

template <unsigned S>
auto f()
{
    if constexpr (S == 1)
        return std::pair{1, 2}; // pair of ints
    else if constexpr (S == 2)
        return std::pair{1.0, 2.0}; // pair of doubles
    else
        return std::pair{0.0f, 0.0f}; // pair of floats
}

This works with gcc 9.2, gcc 10.0, clang 9.0 and clang 10.0.

Next, I wanted to explicitly write the return type as a std::pair for clarity reasons:

EXAMPLE 2

template <unsigned S>
std::pair<auto, auto> f()
{
    if constexpr (S == 1)
        return {1, 2};
    /* ... */
}

Both gcc 9.2/10.0 and clang 9.0/10.0 failed to compile this.

gcc 9.2

error: invalid use of 'auto'
error: template argument 1 is invalid // first argument (auto) of std::pair
error: template argument 2 is invalid // second argument (auto) of std::pair
error: cannot convert '<brace-enclosed initializer list>' to 'int' in return

From the last error message, gcc 9.2 seems to believe that std::pair<auto, auto> is an int . How can this be explained?

gcc 10.0

error: returning initializer list

This error is understandable, however, I expected the constructor of std::pair to be invoked, or is there something I am missing here?

clang 9.0 and 10.0

'auto' not allowed in template argument
excess elements in scalar initializer
no matching function for call to 'f'

Ok, clang doesn't like any of this. From the second error message, it seems that clang also believes the return type is int .

Finally, to fix the error obtained compiling with gcc 10.0, I decided to return a std::pair explicitly:

EXAMPLE 3

template <unsigned S>
std::pair<auto, auto> f()
{
    if constexpr (S == 1)
        return std::pair{1, 2};
    /* ... */
}

clang 9.0 and 10.0

Same as before, but with an additional:

no viable conversion from returned value of type 'std::pair<int, int>' to function return type 'int'

Here clang still thinks we are returning an int ?

gcc 9.2

Same as before.

gcc 10.0

It works!

I guess some features still have to be implemented, or in one of the situations described above, is there a compiler which is right and the other wrong? In my opinion, example 2 should work. Or should it not?

The syntax:

std::pair<auto, auto> f() { return std::pair(1, 2); }
~~~~~~~~~~~~~~~~~~~~~

Was part of the original Concepts TS but was not included in the Concepts proposal that is part of C++20. As such, the only placeholder types in C++20 are auto (and variations thereof like auto** ), decltype(auto) , and constrained placeholders ( Concept auto and variations thereof). This kind of nested placeholder type would be very useful, but is not part of C++20, so that function declaration is ill-formed.

Now, gcc allows it because gcc implemented the Concepts TS and I guess they decided to keep this feature. clang never implemented the TS, so it doesn't.

Either way, this:

std::pair<auto, auto> f() { return {1, 2}; }

Would always be ill-formed. The meaning of the syntax is that we deduce the return type and then require that it matches pair<T, U> for some types T and U . We're basically trying to invoke the invented function:

template <typename T, typename U>
void __f(std::pair<T, U>);

__f({1, 2}); // this must succeed

But you cannot deduce a type from {1, 2} - a braced-init-list doesn't have a type. Perhaps this is something that should be explored (as it's easy to understand at least in a simple case like this), but it has never been allowed. So rejecting it is correct either way.

Lastly:

gcc 9.2 seems to believe that std::pair<auto, auto> is an int . How can this be explained?

For some reason (probably due to our C legacy with implicit int ), when gcc does not recognize or understand a type, it just uses int as the placeholder in error messages. This is super confusing, because obviously it's gcc that came up with int and not the source code. But that's the way it is.

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