问题标签 [list-initialization]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
380 浏览

c++ - 如果大括号闭合列表对于类构造函数的大小错误,则编译时错误

我正在尝试基于数学向量编写一个类:

我希望能够编写这样的代码;

用户期望编写这样的代码是很自然的,对吧?但是,如果我使用错误大小的初始值设定项列表,我希望发生编译时错误,就像这样std::array做一样。

我的第一个想法是std::array用作构造函数/操作符参数,这样会发生隐式转换,然后构造函数会劫持std::array编译时错误。当然,除了我只能写这样的代码:

我想也许可以使用 Variadic 成员模板:

它必须是,typename...而不是double...因为非类型参数必须是整数类型。但后来我遇到了一个缩小的转换错误

大概是因为违反 [8.5.4]/7

缩小转换是隐式转换

— 从整数类型或无作用域枚举类型到浮点类型,除非源是常量表达式并且转换后的实际值将适合目标类型并且在转换回原始类型时将产生原始值,或者

扩展的参数li...不是常量表达式,因此会产生缩小转换错误。据我所知,甚至不可能将函数参数作为常量表达式(也没有多大意义?)。所以我不确定如何沿着这条路线继续前进。显然Vector<2> a = {2.,3.}工作正常,但这给用户带来了负担,要记住只提供浮点文字。

0 投票
1 回答
335 浏览

c++ - 来自相同类型对象的列表初始化优先级

这是带有复制构造函数和初始化列表构造函数的CL结构。我认为这里必须调用复制构造函数,因为根据 C++ 14 标准,8.5.4/3

类型 T 的对象或引用的列表初始化定义如下:
— 如果 T 是类类型并且初始化器列表具有 cv U 类型的单个元素,其中 U 是 T 或从 T 派生的类,则对象是从该元素初始化(通过复制初始化进行复制列表初始化,或通过直接初始化进行直接列表初始化)。
- 除此以外, ...

换句话说,cl2的初始化必须从cl1元素执行,而不是从初始化列表{cl1}执行。Clang 和 gcc 都打印“21”,只有 Visual Studio 打印“2”,我认为它是正确的。
有两个候选构造函数用于获取 CL 类型的参数cl1

  1. 构造函数std::initializer_list<CL>(通过,因为没有从 CL 到 的这种转换std::initializer_list<CL>
  2. 使用 const CL& 复制构造函数(仅与限定转换 non-const->const 完全匹配)

谁是对的?谁的行为是正确的?

0 投票
3 回答
10819 浏览

c++ - 删除了默认构造函数。仍然可以创建对象...有时

对 c++11 统一初始化语法的天真、乐观和哦.. 如此错误的看法

我认为既然 C++11 用户定义类型对象应该使用新{...}语法而不是旧(...)语法构造(除了构造函数重载 forstd::initializer_list和类似参数(例如std::vector:size ctor vs 1 elem init_list ctor))。

好处是:没有狭窄的隐式转换,最麻烦的解析没有问题,一致性(?)。我认为没有问题,因为我认为它们是相同的(除了给出的示例)。

但他们不是。

一个纯粹疯狂的故事

{}调用默认构造函数。

... 除非:

  • 默认构造函数被删除并且
  • 没有定义其他构造函数。

然后看起来它宁愿值初始化对象?...即使对象已经删除了默认构造函数,{}也可以创建一个对象。这难道不是破坏了已删除构造函数的全部目的吗?

...除了以下情况:

  • 该对象有一个已删除的默认构造函数,并且
  • 定义了其他构造函数。

然后它失败了call to deleted constructor

...除了以下情况:

  • 该对象有一个已删除的构造函数,并且
  • 没有定义其他构造函数并且
  • 至少是一个非静态数据成员。

然后它因缺少字段初始化程序而失败。

但是你可以使用它{value}来构造对象。

好的,也许这与第一个异常相同(值初始化对象)

...除了以下情况:

  • 该类有一个已删除的构造函数
  • 并且至少有一个数据成员在类内默认初始化。

那么也不{}{value}不能创建对象。

我确定我错过了一些。具有讽刺意味的是,它被称为统一初始化语法。我再说一遍:UNIFORM初始化语法。

这是什么疯狂?

方案 A

删除了默认构造函数:

方案 B

删除默认构造函数,删除其他构造函数

方案 C

删除了默认构造函数,定义了其他构造函数

方案 D

已删除默认构造函数,未定义其他构造函数,数据成员

方案 E

删除了默认构造函数,删除了 T 构造函数,T 数据成员

方案 F

删除了默认构造函数,类内数据成员初始化器

0 投票
2 回答
99 浏览

c++ - 如何让列表可以隐式转换为我的类对象?

例如,我有一个类Point并且有一个函数

称它为

0 投票
1 回答
137 浏览

c++ - 将聚合初始化为类成员

在这段代码中:

k1我可以很好地初始化一个全局对象。但是尝试在类成员的默认初始化程序上使用相同的语法k2会产生编译器错误(来自 g++-4.8.2 和 g++-5.2.0 的类似错误):

k2在声明时初始化的正确方法是什么?

0 投票
2 回答
527 浏览

c++ - 使用 Boost assign 用变量值初始化类似 JSON 的映射

我正在寻找一种存储 JSON 结构的方法

作为 C++ 中的映射,由boost::assign:::map_list_of. 像这样的东西

其中一些键映射到字符串,其他键映射到子映射(hello 变体)。请注意,我仅限于 C++03,并且我对其他解决方案持开放态度,例如 Boost Proto (DSL)。

0 投票
1 回答
1093 浏览

c++ - 列表初始化是隐式转换吗?

我试图理解在这个列表初始化中发生的隐式转换。从13.3.1.7N3337 开始:

当非聚合类类型 T 的对象被列表初始化(8.5.4)时,重载决策分两个阶段选择构造函数:

  1. 最初,候选函数是类 T 的初始化列表构造函数(8.5.4),参数列表由初始化列表作为单个参数组成。

  2. 如果没有找到可行的初始化列表构造函数,则再次执行重载决议,其中候选函数是类 T 的所有构造函数,参数列表由初始化列表的元素组成。

8.5.4

一个构造函数是一个初始化列表构造函数,如果它的第一个参数是类型std::initializer_list<E>或引用可能std::initializer_list<E>对某种类型有 cv 限定E,并且要么没有其他参数,要么所有其他参数都有默认参数

所以下面的构造函数列表std::map表示

map (initializer_list<value_type> il, const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type());

是候选函数,value_type在这种情况下是pair<const type_index, std::string>。最后来自13.3.3.1.5

如果参数类型是std::initializer_list<X>或“数组X”135,并且初始化列表的所有元素都可以隐式转换为X,则隐式转换序列是将列表元素转换为所需的最差转换X

因此,只要花括号列表的元素隐式转换为pair<const type_index, std::string>. 但这些元素本身也是大括号列表。Pair不采用初始化列表构造函数,从这里看来,括号初始化列表中的复制初始化使用 的第二部分13.3.1.7来构造对象。所以以下内容:

变成:

但这是否被视为隐式转换?如何将使用两个参数的构造函数视为隐式转换?标准对此有何评论?

0 投票
2 回答
1057 浏览

c++ - 调用 C++ 复制构造函数而不是 initializer_list<>

基于此代码

输出是:

默认 ctor

复制者

复制者

在第三种情况下,我将 b 放入应该调用 initializer_list<> 构造函数的大括号初始化中。

相反,复制构造函数带头。

你们中有人能告诉我这是如何工作的吗?为什么?

0 投票
2 回答
86 浏览

c++ - 一个引用的C++多次转发:先复制再移动

考虑以下代码,其中相同的引用被转发两次到一个基类并在那里构造一个元组:

Derived首先调用as中的基类构造函数,Base<T, T>{t, std::forward<_T>(t)}然后调用元组构造函数 usingtup{std::forward<Ts>(ts)...}具有以下原因:

t是一个右值引用时,第一个元组参数应该传递一个左值引用t,因此通过一个副本来构造t,而第二个元组元素应该得到一个右值引用,因此,如果可能的话,使用移动进行构造。

这种方法似乎得到了关于 SO(例如, hereherehere)的几个问题和答案的支持,这些问题和答案表明braced-init 列表对其参数进行从左到右的评估。

但是,当我在一个简单的示例中使用上述代码时,实际行为(始终)与我的预期相反:

这是在 Coliru 上使用 gcc 的示例。(gcc 编译器在这方面显然有过一次错误,但距今已有大约两年了,应该不再有问题了。)

问题:

  • 我在这里的实施或假设哪里错了?
  • 如何修复上述代码以使其行为符合预期:首先复制——然后移动?
0 投票
5 回答
3292 浏览

c++ - 初始化 std::shared_ptr> 使用支撑初始化

我有以下shared_ptr内容map

我想使用braced-init对其进行初始化。是否可以?

我试过了:

但是使用 Xcode 6.3 编译时会出现以下错误:

我尝试了第一个参数(1000.0)的其他变体但没有成功。

任何人都可以帮忙吗?