当前位置: 首页 > 知识库问答 >
问题:

为什么这个initializer\u list构造函数是一个可行的重载?

柴兴贤
2023-03-14
#include <iostream>
#include <string>
#include <initializer_list>

class A
{
 public:
  A(int, bool) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
  A(int, double) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
  A(std::initializer_list<int>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

int main()
{
  A a1 = {1, 1.0};
  return 0;
}

(这个问题是这个问题的后续问题。)

上述程序使用clang35-std=c 11编译失败

init.cpp:15:14: error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]
  A a1 = {1, 1.0};
             ^~~
init.cpp:15:14: note: insert an explicit cast to silence this issue
  A a1 = {1, 1.0};
             ^~~
             static_cast<int>( )

g48-std=c11选择一个产生警告来诊断不正确的狭窄

init.cpp: In function ‘int main()’:
init.cpp:15:17: warning: narrowing conversion of ‘1.0e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
   A a1 = {1, 1.0};
                 ^
init.cpp:15:17: warning: narrowing conversion of ‘1.0e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]

并产生结果

A::A(std::initializer_list<int>)

我的问题是如果A::A(std::initializer\u list

从<代码>13.3.2[超过.匹配.可行]

其次,对于F是一个可行的函数,每个参数都应该存在一个隐式转换序列,该序列将该参数转换为F的相应参数。

4[conv]

表达式e可以隐式转换为类型T,当且仅当声明T=e;对于一些发明的临时变量t,格式良好。

8.5.1[dcl.init.aggr]

如果初始化子句是表达式,并且需要缩小转换来转换表达式,则程序格式错误。

使用8.5.14,因为以下内容格式不正确

std::initializer_list<int> e = {1, 1.0};

{1,1.0}不能隐式转换为std::initializer_list

引用13.3.2,这难道不应该暗示A::A(std::initializer_)列表吗


共有1个答案

巩光誉
2023-03-14

我相信你分析中的问题是声明

int t = 1.0;

确实格式良好——显然存在从doubleint的隐式转换。[over.ics.list]/4还描述了它:

否则,如果参数类型为std::initializer_list

初始值设定项列表中的每个元素都可以隐式转换为int,因此构造函数是可行的,并且是可选择的。然而,只有选择了它,整个过程才会出现错误,[dcl.init.list]/(3.6):

枚举了适用的构造函数,并通过重载解析(13.3,13.3.1.7)选择最佳构造函数。如果需要缩小转换(见下文)来转换任何参数,则程序格式错误。

如您所见,要调用的构造函数是在执行缩小检查之前确定的。换句话说,初始值设定项列表构造函数的可行性并不取决于任何参数的缩小<因此,代码的格式应该是错误的。

获得所需行为的一种方法是在SFINAE中使用构造函数模板

template <typename T, typename=std::enable_if_t<std::is_same<int, T>{}>>
A(std::initializer_list<T>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }

演示。

 类似资料:
  • 主要内容:类继承和初始化,初始化器继承和覆盖在Swift 4中声明的类,结构体和枚举初始化以准备类的实例。 存储属性初始化初始值,对于新实例也初始化值,初始化值以准备初始实例数据。 创建初始化由方法执行。 Swift 4初始化程序与Objective-C的不同之处在于它不返回任何值。 它是在处理之前检查新创建实例的初始化。 Swift 4还提供了“取消初始化”过程,用于在取消分配实例后执行内存管理操作。 存储属性的初始化程序角色 存储属性必

  • 本文向大家介绍请解释Java中的概念,什么是构造函数?什么是构造函数重载?什么是复制构造函数?相关面试题,主要包含被问及请解释Java中的概念,什么是构造函数?什么是构造函数重载?什么是复制构造函数?时的应答技巧和注意事项,需要的朋友参考一下 考察点:JAVA构造函数 当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提供构造函数的情况下,Java编译器会为这个类创建一

  • 问题内容: 这些来自github上的spring amqp示例,位于https://github.com/SpringSource/spring-amqp- samples.git 这些是 什么类型的Java构造函数?它们是吸气剂和吸气剂的捷径吗? 与此相反 问题答案: 这些构造函数被重载以使用调用另一个构造函数。第一个无参数构造函数使用空参数调用第二个。第二呼叫的第三构造(未示出),其必须采取,

  • 我的问题是关于OOP(C)中的构造函数。当我在一个类中将默认构造函数定义为private,并且在main中将该类的一个对象初始化为default时,就会出现默认构造函数不可访问的错误。这很好。但我也在Public部分中使用默认参数构造函数,当我再次在main中初始化对象时,就会出现对函数重载的不明确调用。所以我的问题是,如果不能从main访问私有构造函数,那么编译器应该调用公共部分中的构造函数,这

  • 问题内容: 这就是我遇到问题的方式。我举一个例子: 这可以。现在,我想通过扩展创建一个子类。所以我写道: 一写完,Eclipse中就出现了一个十字架,单击它,我发现了一条消息: 我用谷歌搜索了问题并添加了 Eclipse也建议这样做。现在我有两个问题。 为什么必须强制使用构造函数?AFAIK不需要创建构造函数,因为JAVA编译器会自动创建默认构造函数以继续其操作。同样从消息中,似乎还需要一个默认的