初始化时的多个用户定义转换

问题描述 投票:0回答:1

我知道 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#

c++ visual-c++ type-conversion implicit-conversion standards-compliance
1个回答
0
投票

/permissive-

/std:c++20(默认情况下启用
/permissive-
)来禁用。我找不到更窄的
/Zc:
选项。我也无法找到有关此问题的 Microsoft 文档。
但是,即使在其

版本 2017.2

中也存在相应的 JetBrains ReSharper 警告:

在复制初始化期间应用了多个隐式转换。这是非标准的 Microsoft C++ 扩展

不幸的是,
评论中指向 connect.microsoft.com 的链接

现已失效,我无法在 Visualstudio.com 上找到相应的主题。因此,作为预防措施,我已将此答案中的所有其他链接添加到 https://web.archive.org/

© www.soinside.com 2019 - 2024. All rights reserved.