如果我创建一个
std::vector<int>
并以两种方式初始化它,都会调用 std::initializer_list
构造函数。
std::vector<int> v1{1, 2, 3}; // Calls vector(initializer_list< int >)
std::vector<int> v2 = {1, 2, 3}; // Calls vector(initializer_list< int >)
但是如果我使用一个从
int
隐式转换的类:
struct Imp { Imp(int) {} };
然后第二个初始化方法调用带有一对迭代器的构造函数。
std::vector<Imp> v3{1, 2, 3}; // Calls vector(initializer_list< Imp >)
std::vector<Imp> v4 = {1, 2, 3}; // Calls vector(const int*, const int* ) ???
这只发生在使用GCC 14.2时。使用 Clang 19.1 或 MSVC 19.40 时,
v3
和 v4
都会调用 initializer_list
构造函数。优化级别没有什么区别
为什么
= {}
语法在 GCC 上调用 vector(const int*, const int*)
?
我尝试创建自己的具有两个构造函数的类模板:
template <typename T>
struct Custom {
Custom(std::initializer_list<T>) {}
Custom(const int*, const int*) {}
};
现在
{}
和 = {}
语法都会调用 GCC 上的 initializer_list
构造函数。
Custom<Imp> v5{1, 2, 3}; // Calls Custom(initializer_list< Imp >)
Custom<Imp> v6 = {1, 2, 3}; // Calls Custom(initializer_list< Imp >)
事情变得真正令人困惑的是,如果我专门针对我的隐式转换类型
std::vector
。那么分三种情况:案例1 - 仅提供Imp
ctor
initializer_list
Result - 两种语法都调用提供的 ctor
template <>
struct std::vector<Imp> {
vector(initializer_list<Imp>) {}
};
案例2 - 仅提供std::vector<Imp> v7{1, 2, 3}; // Calls vector(initializer_list< Imp >)
std::vector<Imp> v8 = {1, 2, 3}; // Calls vector(initializer_list< Imp >)
ctor
const int*
结果 - 两种语法都无法编译(没有匹配的构造函数)
template <>
struct std::vector<Imp> {
vector(const int*, const int*) {}
};
案例 3 - 提供两个 ctors
std::vector<Imp> v9{1, 2, 3}; // Error - no matching ctor
std::vector<Imp> vA = {1, 2, 3}; // Error - no matching ctor
Result - template <>
struct std::vector<Imp> {
vector(initializer_list<Imp>) {}
vector(const int*, const int*) {}
};
语法调用
{}
构造函数,而 initializer_list
语法调用 = {}
构造函数const int*
这就是我迷路的地方。
在
案例3中,提供std::vector<Imp> vB{1, 2, 3}; // Calls vector(initializer_list< Imp >)
std::vector<Imp> vC = {1, 2, 3}; // Calls vector(const int*, const int*) ???
构造函数如何允许调用
initializer_list
构造函数?编辑
const int*
无法移动。但这里还有一些带有打印内容的其他示例。
示例 1 - 使用独立类型
std::initializer_list
打印:
struct Imp { Imp(int) {} };
template <typename T>
struct Custom {
Custom(std::initializer_list<T>) { std::printf("initializer_list<T>\n"); }
Custom(const int*, const int*) { std::printf("const int*, const int*\n"); }
};
int main(int argc, char *argv[]) {
Custom<Imp> v{1, 2, 3};
Custom<Imp> w = {1, 2, 3};
示例 2 - 使用 std::vector 专门化
initializer_list<T>
initializer_list<T>
打印:
struct Imp { Imp(int) {} };
template <>
struct std::vector<Imp> {
vector(initializer_list<Imp>) { std::printf("initializer_list<T>\n"); }
vector(const int*, const int*) { std::printf("const int*, const int*\n"); }
};
int main(int argc, char *argv[]) {
std::vector<Imp> v{1, 2, 3};
std::vector<Imp> w = {1, 2, 3};
这两个示例之间的唯一
区别在于,一个是 std:: 专业化,而另一个则不是。 为什么这会改变调用哪个 ctor 重载?