首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >std::pair<auto,auto>返回类型

std::pair<auto,auto>返回类型
EN

Stack Overflow用户
提问于 2020-01-03 12:21:58
回答 1查看 3.2K关注 0票数 17

我在std::pairauto一起玩。在下面的代码中,函数f应该返回依赖于模板参数的类型的std::pair

一个有用的例子:

示例1

代码语言:javascript
运行
复制
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
}

这是与gcc 9.2,gcc 10.0,clang 9.0和clang 10.0的作品。

接下来,出于明确的原因,我希望显式地将返回类型写入std::pair

示例2

代码语言:javascript
运行
复制
template <unsigned S>
std::pair<auto, auto> f()
{
    if constexpr (S == 1)
        return {1, 2};
    /* ... */
}

gcc 9.2/10.0和clang 9.0/10.0都未能对此进行编译。

gcc 9.2

代码语言:javascript
运行
复制
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

从上次的错误信息来看,gcc 9.2似乎认为std::pair<auto, auto>int。这怎么解释呢?

gcc 10.0

代码语言:javascript
运行
复制
error: returning initializer list

这个错误是可以理解的,但是,我希望调用std::pair的构造函数,或者这里缺少什么东西?

clang9.0和10.0

代码语言:javascript
运行
复制
'auto' not allowed in template argument
excess elements in scalar initializer
no matching function for call to 'f'

好吧,克拉昂不喜欢这些。从第二个错误消息来看,clang似乎也认为返回类型是int

最后,为了修复用gcc 10.0编译获得的错误,我决定显式地返回一个std::pair

示例3

代码语言:javascript
运行
复制
template <unsigned S>
std::pair<auto, auto> f()
{
    if constexpr (S == 1)
        return std::pair{1, 2};
    /* ... */
}

clang9.0和10.0

与以前相同,但附加如下:

代码语言:javascript
运行
复制
no viable conversion from returned value of type 'std::pair<int, int>' to function return type 'int'

在这里,clang仍然认为我们正在返回一个int

gcc 9.2

和以前一样。

gcc 10.0

它起作用了!

我想有些特性还需要实现,或者在上面描述的情况中,是否有一个编译器是正确的,另一个是错误的?在我看来,示例2应该有效。还是不应该呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-03 12:35:01

语法:

代码语言:javascript
运行
复制
std::pair<auto, auto> f() { return std::pair(1, 2); }
~~~~~~~~~~~~~~~~~~~~~

是原始概念TS的一部分,但不包括在作为C++20一部分的概念提案中。因此,C++20中唯一的占位符类型是auto (及其变体如auto**)、decltype(auto)和受限占位符(Concept auto及其变体)。这种嵌套占位符类型非常有用,但不是C++20的一部分,因此函数声明格式不正确。

现在,gcc允许它,因为gcc实现了概念TS,我想他们决定保留这个特性。clang从来没有实现TS,所以它没有。

不管怎样,这个:

代码语言:javascript
运行
复制
std::pair<auto, auto> f() { return {1, 2}; }

都是畸形的。语法的意思是,我们推断返回类型,然后要求它与某些类型的pair<T, U> ( TU )匹配。我们基本上是在尝试调用所发明的函数:

代码语言:javascript
运行
复制
template <typename T, typename U>
void __f(std::pair<T, U>);

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

但是您不能从{1, 2}推断出一个类型--一个带大括号的列表没有类型。也许这是应该探索的(因为它很容易理解,至少在这样一个简单的情况下),但它从来没有被允许。因此,不管是哪种方式,拒绝它都是正确的。

最后:

gcc 9.2似乎认为std::pair<auto, auto>int。这怎么解释呢?

由于某些原因(可能是由于我们的C遗留的隐式int),当gcc不识别或理解一个类型时,它只是在错误消息中使用int作为占位符。这太让人困惑了,因为显然是gcc提出了int,而不是源代码。但事情就是这样。

票数 23
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59578575

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档