首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >std::initializer_list{x,y,z} (CTAD)有效吗?

std::initializer_list{x,y,z} (CTAD)有效吗?
EN

Stack Overflow用户
提问于 2019-03-17 08:25:41
回答 2查看 426关注 0票数 19

在显式构造std::initializer_list<U>时,是否可以推导模板参数(例如,使用类模板参数演绎(CTAD) )?

换言之,我知道以下声明是有效的:

代码语言:javascript
运行
复制
std::initializer_list<int> x1{1, 2, 3};
std::initializer_list<int> x2 = {1, 2, 3};
auto x3 = std::initializer_list<int>{1, 2, 3};

但以下陈述是否也有效?

代码语言:javascript
运行
复制
std::initializer_list x1{1, 2, 3};
std::initializer_list x2 = {1, 2, 3};
auto x3 = std::initializer_list{1, 2, 3};

编译器对于是否可以推断出std::initializer_list的模板参数存在分歧:

代码语言:javascript
运行
复制
#include <initializer_list>

struct s {
    s(std::initializer_list<int>);
};

void f() {
    std::initializer_list x1{1, 2, 3};         // Clang ERROR; GCC OK;    MSVC OK
    std::initializer_list x2 = {1, 2, 3};      // Clang ERROR; GCC OK;    MSVC OK
    auto x3 = std::initializer_list{1, 2, 3};  // Clang ERROR; GCC OK;    MSVC OK

    s x4(std::initializer_list{1, 2, 3});      // Clang ERROR; GCC ERROR; MSVC OK
    s x5{std::initializer_list{1, 2, 3}};      // Clang ERROR; GCC OK;    MSVC OK
    s x6 = s(std::initializer_list{1, 2, 3});  // Clang ERROR; GCC OK;    MSVC OK
    s x7 = s{std::initializer_list{1, 2, 3}};  // Clang ERROR; GCC OK;    MSVC OK
    s x8 = std::initializer_list{1, 2, 3};     // Clang ERROR; GCC OK;    MSVC OK

    void g(std::initializer_list<int>);
    g(std::initializer_list{1, 2, 3});         // Clang ERROR; GCC OK;    MSVC OK
}

(请参阅编译器资源管理器上的示例。)

经测试的编者:

  • 使用-std=c++17 -stdlib=libc++-std=c++17 -stdlib=libstdc++的Clang版本7.0.0
  • GCC版本8.3与-std=c++17
  • 使用/std:c++17的MSVC版本19.16
EN

Stack Overflow用户

发布于 2020-08-15 14:08:27

这是一个Clang错误,在Nicol Bolas的“永不改变的答案”的评论中得出结论。总之,与任何类类型一样,std::initializer_list有一个编译器提供了演绎指南[over.match.class.deduct]第1.3节

从假设的构造函数C(C)派生出一个额外的函数模板,称为复制演绎候选。

这意味着std::initializer_list具有编译器隐式声明的演绎指南:

代码语言:javascript
运行
复制
template <class T>
initializer_list (initializer_list <T>) -> initializer_list <T>;

当使用非空的初始化程序列表参数来推断此演绎指南的T时,标准的下列规则被应用到[temp.deduct.call]§1

如果从P中删除引用和cv-限定符给出了一些P‘和N的std::初始化器_ list 或P‘n,并且参数是一个非空的初始化程序列表(dcl.init.list),那么将独立地对初始化程序列表的每个元素执行推导,并将P’作为单独的函数模板参数类型P‘i和ith初始化器元素作为相应的参数。

因此,应该将T推导为int,这样类模板参数推导就会成功。

免责声明:我不是部族的拥护者..。

票数 2
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55205176

复制
相关文章

相似问题

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