Clang和GCC 不同意关于接受这个代码。
什么是标准要求的行为?
#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++,所以标准可能是模糊的,但我假设有一种行为是正确的。
发布于 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]。我们从哪里得到了这个臭名昭著的项目清单:
这告诉我们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看起来真的很具体。
https://stackoverflow.com/questions/66124794
复制相似问题