构造函数、初始化器列表以及g++和clang中的不同行为
Constructor, initializer list and different behaviour in g++ and clang
这是简化的代码:
#include <vector>
class VInitList
{
public:
explicit VInitList(std::vector<int> v){}
};
int main()
{
VInitList vil({{}});
}
并用g++5.2.1编译得到这个错误:
error: call of overloaded ‘VInitList(<brace-enclosed initializer list>)’ is ambiguous
VInitList vil({{}});
^
main.cpp:6:5: note: candidate: VInitList::VInitList(std::vector<int>)
VInitList(std::vector<int> v){}
^
main.cpp:3:7: note: candidate: constexpr VInitList::VInitList(const VInitList&)
class VInitList
^
main.cpp:3:7: note: candidate: constexpr VInitList::VInitList(VInitList&&)
当我看到编译器错误时,我发现我错写了{{}}
(是的,不要对我刻薄),但我仍然无法理解这个错误。IMHO编译器必须清除多余的{}或返回语法错误。
然后我尝试编译这个:
std::vector<int> v = {{{}}};
其按预期工作。
但是std::vector<int> v = {{{}}};
不会按照你的想法去做;它用一个初始化为零的int
元素初始化向量。这是因为int
可以列表初始化:
int i{}; // assert(i == 0)
因此std::vector<int> v = {{{}}};
被解析为:
std::vector<int> v = {{{}}};
^-- int
^-- initializer_list<int>
^-- vector<int>
同样,如果你写
VInitList vil{{{}}};
^-- int
^-- vector<int>
^-- VInitList
所包含的vector<int>
具有初始化为零的1个元素。(initializer_list<int>
阶段可以省略,因为vector(initializer_list<int>)
构造函数是非explicit
)。
因此VInitList vil({{}});
可以解析为:
VInitList vil({{}});
^-- int
^-- vector<int>
或作为
VInitList vil({{}});
^-- vector<int>
^-- VInitList
在第一种情况下,vector
具有1个元素;在第二种情况下,它是空的。gcc拒绝您的代码也是好的。
Clang只是将其解析为前者;我不确定哪一个是正确的。
相关文章:
- 奇怪的结构&GCC&clang(void*返回类型)
- 数据成员SFINAE的C++17测试:gcc vs clang
- 当我编译webrtc服务器时,Windows上只支持clang-cl
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 我可以将一个用clang c++11编译的对象与另一个用c++17编译的对象链接起来吗
- Clang bug?使用指针作为模板参数
- clang整洁10忽略了我的NOLINT命令
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 在clang++预处理器中确定gcc工具链版本
- 为什么 Clang 不允许"and"作为函数名称?
- 带有 -stdlib=libc++ 的 clang++ 9.0.1 找不到<optional>
- clang格式:宏的缩进
- CLANG 编译器 说:变量"PTR"可能未初始化
- clang格式:禁用排序包含
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- gcc和clang在表达式是否为常量求值的问题上存在分歧
- 循环展开 - G++ 与 Clang++
- 如何使用Clang/GCC在Mac上为C/C++设置VSCode
- 一位朋友将模板函数缩写为clang和gcc
- 类模板参数推导-clang和gcc不同