简体   繁体   English

标准::对<auto, auto>返回类型

[英]std::pair<auto, auto> return type

I was playing around with auto in std::pair .我在std::pair玩弄auto In the below code, function f is supposed to return a std::pair of types which depend on a template parameter.在下面的代码中,函数f应该返回依赖于模板参数的std::pair类型。

A working example:一个工作示例:

EXAMPLE 1例 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.这适用于 gcc 9.2、gcc 10.0、clang 9.0 和 clang 10.0。

Next, I wanted to explicitly write the return type as a std::pair for clarity reasons:接下来,为了清晰起见,我想将返回类型显式写为std::pair

EXAMPLE 2例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/10.0 和 clang 9.0/10.0 都无法编译这个。

gcc 9.2海湾合作委员会 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 .从最后一条错误消息来看,gcc 9.2 似乎认为std::pair<auto, auto>是一个int How can this be explained?这怎么解释?

gcc 10.0海湾合作委员会 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?这个错误是可以理解的,但是,我希望调用std::pair的构造函数,或者我在这里遗漏了什么?

clang 9.0 and 10.0叮当 9.0 和 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.好吧,clang 不喜欢这些。 From the second error message, it seems that clang also believes the return type is int .从第二条错误消息来看,似乎 clang 也认为返回类型是int

Finally, to fix the error obtained compiling with gcc 10.0, I decided to return a std::pair explicitly:最后,为了修复使用 gcc 10.0 编译时出现的错误,我决定明确返回一个std::pair

EXAMPLE 3例3

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

clang 9.0 and 10.0叮当 9.0 和 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 ?这里 clang 仍然认为我们正在返回一个int

gcc 9.2海湾合作委员会 9.2

Same as before.和之前一样。

gcc 10.0海湾合作委员会 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.在我看来,示例 2 应该有效。 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.是原始概念 TS 的一部分,但未包含在作为 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).因此,C++20 中唯一的占位符类型是auto (及其变体,如auto** )、 decltype(auto)和受约束的占位符( Concept auto及其变体)。 This kind of nested placeholder type would be very useful, but is not part of C++20, so that function declaration is ill-formed.这种嵌套的占位符类型非常有用,但不是 C++20 的一部分,因此函数声明是格式错误的。

Now, gcc allows it because gcc implemented the Concepts TS and I guess they decided to keep this feature.现在,gcc 允许它,因为 gcc 实现了概念 TS,我猜他们决定保留这个功能。 clang never implemented the TS, so it doesn't. clang 从未实现过 TS,所以它没有。

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 .语法的含义是我们推导出返回类型,然后要求它与某些类型TU pair<T, 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.但是您不能从{1, 2}推导出类型 - 花括号初始化列表没有类型。 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 . gcc 9.2 似乎相信std::pair<auto, auto>是一个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.出于某种原因(可能是由于我们的 C 遗留的隐式int ),当 gcc 无法识别或理解类型时,它只是使用int作为错误消息中的占位符。 This is super confusing, because obviously it's gcc that came up with int and not the source code.这非常令人困惑,因为显然是 gcc 提出了int而不是源代码。 But that's the way it is.但事情就是这样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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