问题描述
在 GCC 7.1 上,以下代码仅在显式构造函数具有默认参数时才编译。运行时,b
的大小为1。没有默认参数,编译错误。
在 Clang 上,代码以任何一种方式编译。当它运行时,b
的大小为 0。这是因为一个空向量被复制构造到 b
中。
两者都使用 C++17 进行了测试。
#include <stdio.h>
#include <vector>
#include <iostream>
struct TestStruct {
TestStruct(){}
};
struct TestStructExplicit {
#if 1
explicit TestStructExplicit(int x=0){}
#else
explicit TestStructExplicit(int x){}
explicit TestStructExplicit(){}
#endif
};
int main()
{
//note the nested braces
std::vector<TestStruct> a({{}});
std::vector<TestStructExplicit> b({{}});
std::cout << "SIZE a " << a.size() << std::endl;
std::cout << "SIZE b " << b.size() << std::endl;
}
相关的 Godbolt 链接 https://godbolt.org/z/s5banG54G 与 GCC 和 Clang 的输出。
根据标准,这里的正确行为是什么?我认为下面的 C++17 标准段落说不能使用显式构造函数,这是否意味着这是 GCC 错误? -
16.3.1.7 列表初始化[over.match.list] 1 当非聚合类类型 T 的对象被列表初始化时,11.6.4 指定重载决议 根据本节的规则执行,重载决议分两个阶段选择构造函数: (1.1) — 最初,候选函数是类 T 的初始化列表构造函数 (11.6.4) 和 参数列表由作为单个参数的初始值设定项列表组成。 (1.2) — 如果找不到可行的初始化列表构造函数,则再次执行重载解析,其中 候选函数是类 T 的所有构造函数,参数列表由元素组成 的初始化列表。 如果初始值设定项列表没有元素并且 T 具有默认构造函数,则省略第一阶段。在复制列表初始化中,如果选择了显式构造函数,则初始化是格式错误的。 [注:这不同于 其他情况 (16.3.1.3,16.3.1.4),其中只考虑转换构造函数进行复制初始化。 仅当此初始化是重载解析的最终结果的一部分时,此限制才适用。 — 尾注 ]
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)