首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Clang或GCC拒绝/接受此CTAD代码是否正确?

Clang或GCC拒绝/接受此CTAD代码是否正确?
EN

Stack Overflow用户
提问于 2021-02-09 18:19:27
回答 1查看 1K关注 0票数 25

Clang和GCC 不同意关于接受这个代码。

什么是标准要求的行为?

代码语言:javascript
复制
#include <utility>
#include <iostream>
#include <vector>

int main()
{
    std::vector pairs = {std::pair{1,11},{2,22}, {3,33}};
    for (const auto& p: pairs) {
        std::cout << p.second << std::endl;
    }
}

注意:我知道这是C++,所以标准可能是模糊的,但我假设有一种行为是正确的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-09 19:24:51

CTAD过程很大程度上是由[over.match.class.deduct]定义的。广义地说,重载集是该类型的所有可访问构造函数,以及任何演绎指南。并根据此规则解析重载集:

初始化和重载解析按照dcl.init和over.match.ctor、over.match.copy或over.match.list中的描述执行。

因为“执行的初始化类型”绝对是列表初始化,所以我们继续讨论[over.match.list]。我们从哪里得到了这个臭名昭著的项目清单:

  • 最初,候选函数是类T的初始化-列表构造函数(dcl.init.list),参数列表由作为单个参数的初始化程序列表组成。
  • 如果找不到可行的初始化程序列表构造函数,则再次执行重载解析,其中候选函数是类T的所有构造函数,参数列表由初始化程序列表的元素组成。

这告诉我们initializer-list constructors是被排序的;它们首先被赋予过载解析的漏洞,并且以一种非常具体的方式(即构建一个std::initializer_list并将它作为参数传递)。然而,Clang给出了一个明显的错误:

注:候选函数模板不可行:最多需要2个参数,但提供了3个向量(initializer_list __l,

也就是说,它试图调用那个构造函数,就好像“参数列表由初始化程序列表的元素组成。”这表明Clang在通过CTAD进行列表初始化时跳过了第一个要点。事实上,在大括号内的列表“修正”周围添加双亲,这也表明这就是正在发生的事情。

奇怪的是,它适用于简单的类型,比如初始化器-整数列表。如果您显式地将每个成员命名为pair,它就会起作用。而Clang可以auto-deduce -- {std::pair{1,11}, {2,22}, {3,33}}生产的initializer_list的类型--非常好。所以这个bug看起来真的很具体。

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

https://stackoverflow.com/questions/66124794

复制
相关文章

相似问题

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