以均匀初始化的尾随逗号
Trailing comma in uniform initialization
当我在统一初始化期间使用尾逗号时,是否存在潜在的语义差异?
std::vector< std::size_t > v1{5, }; // allowed syntax
std::vector< std::size_t > v2{10};
我可以使用尾随逗号使编译器选择std::vector::vector(std::initializer_list< std::size_t >)
构造函数,而不是std::vector::vector(std::size_t, const std::size_t &)
,或者是否还有其他技巧?
我可以使用它来检测是否存在 std::initializer_list
-constructor过载?
考虑以下代码,必须选择哪个构造函数?
struct A { A(int) { ; } A(double, int = 3) { ; } };
A a{1};
A b{2, };
在两种情况下选择gcc 8
,A(int)
都接受此代码。
首先,C 语法规则使 Braced-Init-list 的尾随,
可选。引用dcl.init/1
声明器可以指定标识符的初始值 宣布。标识符指定一个正在初始化的变量。这 [dcl.init]其余部分中描述的初始化过程 也适用于其他句法上下文指定的初始化, 例如函数参数的初始化([expr.call])或 返回值的初始化([stmt.return])。
initializer: brace-or-equal-initializer ( expression-list ) brace-or-equal-initializer: = initializer-clause braced-init-list initializer-clause: assignment-expression braced-init-list braced-init-list: { initializer-list ,opt } { designated-initializer-list ,opt } { }
其次,您几乎不能超越过载分辨率系统。如果您使用此类语法并且可以使用此类std::initializer_list
构造函数,它将始终使用std::initializer_list
构造函数。
dcl.init.list/2:
如果第一个 参数为类型std :: initializer_list或引用 可能E的CV合格的std :: initializer_list用于某种类型E,并且 要么没有其他参数,否则所有其他参数都有 默认参数。 [注意:初始化列表构造函数比列表限制中的其他构造函数([over.match.list])....
下面的程序打印Using InitList
:
#include <iostream>
#include <initializer_list>
struct X{
X(std::initializer_list<double>){ std::cout << "Using InitListn"; }
X(int){ std::cout << "Using Single Arg ctorn"; }
};
int main(){
X x{5};
}
尽管5
是int
类型的字面意义,但选择单个参数构造函数应该是有意义的,因为它是完美的匹配。std::initializer_list<double>
构造函数需要double
的列表。但是,该规则有利于std::initializer_list<double>
,因为它是 initiber-list-list构造函数。
结果,即使下面的程序也因缩小转换而失败:
#include <iostream>
#include <initializer_list>
struct Y{
Y(std::initializer_list<char>){ std::cout << "Y Using InitListn"; }
Y(int, int=4){ std::cout << "Y Using Double Arg ctorn"; }
};
int main(){
Y y1{4777};
Y y2{577,};
Y y3{57,7777};
}
响应您下面的评论:" ,如果与std :: prinistizer_list没有过多载荷,或者它不是第一个构造函数的参数?" - 然后,Overload分辨率不选择它。演示:
#include <iostream>
#include <initializer_list>
struct Y{
Y(int, std::initializer_list<double>){ std::cout << "Y Using InitListn"; }
Y(int, int=4){ std::cout << "Y Using Double Arg ctorn"; }
};
int main(){
Y y1{4};
Y y2{5,};
Y y3{5,7};
}
打印:
Y Using Double Arg ctor
Y Using Double Arg ctor
Y Using Double Arg ctor
如果没有可用的 initializer-list构造函数,则 {initializer-list...,}
初始化器几乎落在dcl.init/16的 direct初始化 16,其语义被涵盖由DCL.Init/16
no。该逗号是使预处理器宏观技巧在没有编译错误的情况下起作用的让步。这对您的数据类型或大小没有任何意义。
- 是否可以初始化不可复制类型的成员变量(或基类)
- C++使用整数的压缩数组初始化对象
- C++初始化基类
- 多成员Constexpr结构初始化
- 复制列表初始化的隐式转换的等级是多少
- 内联映射初始化的动态atexit析构函数崩溃
- 如何在C++中初始化嵌套类中的2个memeber
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 没有用于初始化C++中的变量模板的匹配构造函数
- 在未初始化映射的情况下,将值插入到映射的映射中
- C++成员初始化
- 为什么在C++中首先初始化成员类
- 同时具有"聚合初始化"和"模板推导"
- 初始化具有非默认构造函数的std::数组项的更好方法
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 在C和C++中初始化结构中的数组
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 在函数内部的声明中初始化数组,并在外部使用它
- 继承:构造函数,初始化C++11中基类的类C数组成员