C std :: vector Initializer_list过载歧义(g /clang )
C++ std::vector initializer_list overload ambiguity (g++/clang++)
考虑以下代码:
#include <vector>
#define BROKEN
class Var {
public:
#ifdef BROKEN
template <typename T>
Var(T x) : value(x) {}
#else
Var(int x) : value(x) {}
#endif
int value;
};
class Class {
public:
Class(std::vector<Var> arg) : v{arg} {}
std::vector<Var> v;
};
clang (7.0.1)是否定义了BROKEN
,毫无疑问地对此进行了编译,但是G (8.2.1)如果定义了BROKEN
,则会引起错误:
main.cpp:9:20: error: cannot convert ‘std::vector<Var>’ to ‘int’ in initialization
Var(T x) : value(x) {}
^
据我所知,此处使用的统一的Intialization在两种情况下都应选择std::vector(std::vector&&)
构造函数。但是,显然,g++
相反,将{arg}
视为初始化列表,并尝试使用应用于向量的Var
初始化v
的第一个元素,该元素将其应用于向量。
如果未定义BROKEN
,G 显然足够聪明,可以意识到initializer_list过载不起作用。
哪个是正确的行为,或者标准允许?
断开定义的GCC
破裂未定义的GCC
折断的clang
这是解决该问题的两种方法:
class Var {
public:
#ifdef BROKEN
template <typename T>
Var(T x, typename std::enable_if<std::is_convertible<T, int>::value>::type* = nullptr) : value(x) {}
#else
Var(int x) : value(x) {}
#endif
int value;
};
现场演示。
或:
class Class {
public:
Class(std::vector<Var> arg) : v(arg) {}
std::vector<Var> v;
};
现场演示。
现在显然在GCC尝试时使用模板参数作为初始化列表。当使用括号并定义初始化列表时,初始化列表具有更高的优先级,然后复制构造函数。
因此,添加适当的enable_if
解决了问题,因为它可以保护创建构造函数的初始化列表版本。在C 中,20个概念将以更好的方式解决此问题。
,当使用括号用于初始化 v
初始化列表时,不太可取。
我不确定谁是对的(Imo 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上崩溃
- C std :: vector Initializer_list过载歧义(g /clang )
- g++和clang++-删除由重载转换运算符歧义获取的指针
- GCC声明友元函数是重载的,有歧义调用,clang编译
- 模板默认实参SFINAE对clang有歧义,但对g++很好