JSQ*_*reD 5 c++ standards-compliance type-conversion visual-c++ implicit-conversion
我知道 C++ 在类型之间转换时只允许单个用户定义的隐式转换。然而,我最近遇到了一种情况,似乎在初始化时允许双重用户定义的隐式转换。
考虑以下类:
//fractions
class Rational {
public:
    int num, den;
    // default constructor, etc.
    Rational(int n) : num(n), den(1) {} // NOT explicit
    // arithmetic and compound assignment defined between two Rational's.
};
//numbers of the form a + b sqrt(N), where a, b are of type R
template<typename R, int N>
class RingExtension {
public:
    R a, b;
    // default constructor, etc.
    RingExtension<R, N>(R a) : a(a), b(0) {} // NOT explicit
    // arithmetic and compound assignment defined between two RingExtension<R, N>'s.
};
正如预期的那样,以下内容将无法编译:
int main() {
    RingExtension<Rational, 2> x;
    x /= 3; // ERROR! Can't do the conversion int -> Rational -> RingExtension<Rational, 2>
    x /= (Rational)3; // this does work
}
但是,以下内容可以在 Visual Studio 2013 中编译:
int main() {
    RingExtension<Rational, 2> x = 3; // int -> Rational -> RingExtension<Rational, 2>
}
为什么在后一种情况下允许双重用户定义转换?在这种特殊情况下,Visual Studio 是否不符合标准?或者初始化标准中有一些例外吗?
编辑:正如 Kerrek SB 建议的那样,我已经通过 Wandbox 在 clang 和 gcc 中测试了我的代码。正如人们所期望的那样,两个编译器都会在初始化时抛出错误。问题仍然存在,谁错了?Visual Studio 似乎过于宽松,但如果有人能证实这一点那就太好了。
编辑:这些类的完整源代码,包括 main() 函数,可以在这里找到: http: //pastebin.com/JNSvkwi0#
这似乎是一个非标准的 Microsoft 扩展,可以通过传递/permissive-or来禁用/std:c++20(/permissive-默认情况下启用)。我无法找到更窄的/Zc:选择。我也无法找到有关此问题的 Microsoft 文档。
然而,甚至早在2017.2 版本中就有相应的 JetBrains ReSharper 警告:
复制初始化期间应用了不止一种隐式转换。这是非标准的 Microsoft C++ 扩展
不幸的是,评论中指向 connect.microsoft.com 的链接现已失效,我无法在 Visualstudio.com 上找到相应的主题。因此,作为预防措施,我已将此答案中的所有其他链接添加到https://web.archive.org/ 。
| 归档时间: | 
 | 
| 查看次数: | 222 次 | 
| 最近记录: |