std :: initializer_list {x,y,z}(CTAD)有效吗? [英] Is std::initializer_list{x, y, z} (CTAD) valid?

查看:79
本文介绍了std :: initializer_list {x,y,z}(CTAD)有效吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

When constructing an std::initializer_list<U> explicitly, can the template argument (U) be deduced (using class template argument deduction (CTAD), for example)?

换句话说,我知道以下语句是有效的:

In other words, I know that the following statements are valid:

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};

但是以下语句也有效吗?

but are the following statements also valid?

std::initializer_list x1{1, 2, 3};
std::initializer_list x2 = {1, 2, 3};
auto x3 = std::initializer_list{1, 2, 3};






编译器不同意<$的模板参数可以推断出c $ c> std :: initializer_list :

#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 ++ 的Clang版本7.0.0 -std = c ++ 17 -stdlib = libstdc ++

  • GCC版本8.3与 -std = c ++ 17

  • MSVC版本19.16,具有 / std:c ++ 17

  • Clang version 7.0.0 with -std=c++17 -stdlib=libc++ and with -std=c++17 -stdlib=libstdc++
  • GCC version 8.3 with -std=c++17
  • MSVC version 19.16 with /std:c++17

推荐答案

Clang是唯一正确的编译器。是的,真的。

Clang is the only compiler that is correct. Yes, really.

当编译器看到没有模板参数的模板名称时,它必须查看模板的推导指南并将其应用于括号中的参数。 -init-list。 initializer_list 没有任何明确的推论指南,因此它使用可用的构造函数。

When the compiler sees a template name without template parameters, it has to look at the deduction guides of the template and apply them to the arguments in the braced-init-list. initializer_list doesn't have any explicit deduction guides, so it uses the available constructors.

唯一可公开访问的构造函数 initializer_list 具有的是其复制/移动构造函数及其默认构造函数。不能通过可公开访问的构造函数来从括号初始列表创建 std :: initializer_list 。通过列表初始化完成,这是仅限编译器进程。只有编译器才能执行构建一个编译器所需的步骤顺序

The only publicly accessible constructors that an initializer_list has are its copy/move constructors and its default constructor. Creating a std::initializer_list from a braced-init-list isn't done through publicly accessible constructors. It's done through list-initialization, which is a compiler-only process. Only the compiler can perform the sequence of steps needed to build one.

鉴于所有这些,除非您在 initializer_list 上使用CTAD,否则应该是不可能的从现有列表中复制。最后一部分可能是其他编译器在某些情况下如何使其工作。在推论方面,他们可以将括号初始列表推导为 initializer_list< T> 本身,而不是推导 [over.match.list] 到,因此推论指南会看到复制操作。

Given all of this, it should not be possible to use CTAD on initializer_lists, unless you're copying from an existing list. And that last part is probably how the other compilers make it work in some cases. In terms of deduction, they may deduce the braced-init-list as an initializer_list<T> itself rather than as a sequence of parameters to apply [over.match.list] to, so the deduction guide sees a copy operation.

这篇关于std :: initializer_list {x,y,z}(CTAD)有效吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆