为什么移动和值构造函数的组合对MSVC有歧义,而对C++17及更高版本中的Clang和GCC没有歧义
Why is this combination of move and value constructor ambigous for MSVC but not for Clang and GCC in C++17 and above
我有以下代码
struct R {
int i_ = 8;
R() = default;
R(R const& o) = default;
R(R&& o) = default;
R(int i) : i_(i) {}
operator int() const { return i_; }
};
struct S {
R i_;
operator R() const { return i_; }
operator int() const { return static_cast<int>(i_); }
};
int main() {
S s;
R r0(s);
R r = static_cast<R>(s);
float af[] = {1,2,3};
float f1 = af[s];
float f2 = af[r];
}
它在C++17和C++20的Clang和GCC上编译得很好(不适用于C++<17(,但抱怨
'R::R': ambiguous call to overloaded function
note: could be 'R::R(R &&)'
note: or 'R::R(int)'
对于所有可用的标准,在MSVC中。
我试图通过比较MSVC、Clang和GCC来找到语言一致性的差异,也尝试了对MSVC的/permission,但还找不到任何解释。
- 谁是对的(任何原因(以及
- 如何在不放弃R中的
R&&
和int i
因子或将强制转换operator int()
标记为显式的情况下为MSVC编译它
这里有一个相当拥挤的godbolt,包括一个可能的解决方法。
这是CWG 2327,它目前没有解决方案,但gcc和clang似乎做到了"正确的做法"问题如下:
考虑这样一个例子:
struct Cat {}; struct Dog { operator Cat(); }; Dog d; Cat c(d);
进入9.4[dcl.init]项目符号17.6.2:
否则,如果初始化是直接初始化,或者如果是复制初始化,其中源类型的cv不合格版本与目标类的类或派生类相同,则考虑构造函数。枚举适用的构造函数(12.2.2.4[over.match.cctor](,并通过重载解析(12.2[over.match](选择最佳构造函数。调用如此选择的构造函数来初始化对象,初始化器表达式或表达式列表作为其参数。如果没有应用构造函数,或者重载解析不明确,则初始化格式不正确。
Overload resolution选择
Cat
的move构造函数。根据9.4.4[dcl.init.ref]项目符号5.2.1.2,初始化构造函数的Cat&&
参数会产生一个临时的。这排除了在这种情况下省略副本的可能性。这似乎是在保证省略副本的措辞变化中的疏忽。在这种情况下,我们应该同时考虑构造函数和转换函数,就像我们对副本初始化一样,但我们需要确保这不会引入任何新的问题或歧义。
这里的情况类似,只是更复杂。使用任一:
R r0(s);
R r = static_cast<R>(s);
我们有一个来自s
的转换函数,它给出了一个prvalueR
,这是一个比我们可以使用的任何其他路径都更好的路径——无论是通过R
的move构造函数还是R(int)
。但我们只是没有一条规则来说明这就是我们应该做的
gcc和clang似乎在C++17或更高版本上实现了所需的行为(我们保证了副本省略(,尽管没有任何所需行为的措辞。另一方面,msvc似乎遵循了指定的规则(我认为这确实说明了这种情况不明确(。
- 在 C++11 及更高版本中,有没有办法初始化初始值设定项列表中的向量?
- 如何获得CMake Tools以在Visual Studio Code中编译具有C++11(或更高版本)功能的程序?
- 如何将_RICHEDIT_VER(riched20.dll)升级到版本3或更高版本
- 在 Visual Studio 2010(及更高版本)中定义包含或链接路径变量的位置
- C++14 及更高版本是否允许 Lambda 函数的默认参数?如果是这样,怎么办?
- 片段着色器中的"错误:在 GLSL 1.30 及更高版本中禁止使用非常量表达式索引的采样器数组"
- 在Mac OS X Mountain Lion(或更高版本)和Linux上使用X11/Xlib.h
- 对于我在 Microsoft Visual C++ IDE (2005 或更高版本)的本机 win32 项目中编写的应用
- 将用户输入绑定到UE4.22.3及更高版本中的UActorComponent方法
- 使用 C++17 或更高版本对向量中的元素对求和的最'functional'方法?
- 在C 11或更高版本中,是否可以通过Lambda来实现单方法纯Virtual C 接口
- 是 GCC 6.2 或更高版本中的 C++20 实验范围
- 如何在 CMake 3.7 及更高版本中表达 PGO 依赖项
- C++11及更高版本:shared_ptr,用于管理由低级C库提供的系统资源
- 如何在 CMake 目标上请求 C++11 或更高版本
- 如何在Windows和更高版本上保留内存,并将文件映射到内存中
- 谁能帮助我在 4.0 及更高版本上实现 Android Blur,而无需学习 Renderscript
- 如何使用Windows Server 2003及更高版本上的虚拟磁盘服务(VDS)登录ISCSI目标
- 区分 VC++ 2010 和更高版本的编译器版本
- flens lapack:需要GNU GCC 4.7版或更高版本!我的mac有