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&&)
当我看到编译错误时,我发现我写错了{{}}
(是的,不要对我不好),但我仍然无法理解错误。恕我直言,编译器必须摆脱额外的 {} 或 return 语法错误。
然后我试着编译这个:
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只解析为前者;我不确定哪个是正确的。
这是简化代码:
#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&&)
当我看到编译错误时,我发现我写错了{{}}
(是的,不要对我不好),但我仍然无法理解错误。恕我直言,编译器必须摆脱额外的 {} 或 return 语法错误。
然后我试着编译这个:
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只解析为前者;我不确定哪个是正确的。