The following code, a simplified version of code found in the googlemock project, fails to compile in Visual Studio 2015 Update 1, but it compiles on clang [Apple LLVM version 7.0.0 (clang-700.1.76)].
以下代码是在googlemock项目中找到的简化版代码,在Visual Studio 2015 Update 1中无法编译,但它在clang [Apple LLVM 7.0.0版本(clang-700.1.76)]上编译。
struct ConvertibleFromAny
{
ConvertibleFromAny(int a_value);
template <typename T>
ConvertibleFromAny(const T& a_value);
};
template <typename T>
struct Matcher
{
Matcher(T value);
};
template <typename Rhs>
struct EqMatcher
{
explicit EqMatcher(const Rhs& rhs);
template <typename Lhs>
operator Matcher<Lhs>() const;
};
int main()
{
EqMatcher<ConvertibleFromAny> em(1);
Matcher<ConvertibleFromAny> m = em;
return 0;
}
The error occurs at the assignment statement
错误发生在赋值语句中
Matcher<ConvertibleFromAny> m = em;
and the error message is
错误信息是
error C2440: 'initializing': cannot convert from 'EqMatcher<ConvertibleFromAny>' to 'Matcher<ConvertibleFromAny>'
note: No constructor could take the source type, or constructor overload resolution was ambiguous
I can naively see an ambiguity between a member call to
我可以天真地看到成员调用之间的模糊性
EqMatcher<ConvertibleFromAny>::operator Matcher<ConvertibleFromAny>()
and an initialization conceptually similar to
初始化的概念与
Matcher<ConvertibleFromAny> m(ConvertibleFromAny<EqMatcher<ConvertibleFromAny>>(em))
My guess is that clang rules out the second option.
我猜clang排除了第二种选择。
EDIT: Inspired by T.C.'s comment I tested the following:
编辑:灵感来自于教学楼。我测试了以下内容:
struct A
{
};
struct X
{
X(const A&);
};
struct B
{
B(const X&);
};
int main()
{
A a;
B b = a;
}
It compiles with VS 2015, but not with clang. I have not been able to find any references that documents that the Visual C++ implementation intentionally deviates from the standard in this regard.
它编译VS 2015,但不编译clang。我没有找到任何参考文献,证明Visual c++实现在这方面故意偏离了标准。
Is this a well-known problem?
这是一个众所周知的问题吗?
2 个解决方案
#1
12
Both your code samples produce the expected result with VS2015 Update 1, if I enable the "Disable Language Extensions" (/Za
) flag. That is, the first one compiles, the second one does not.
如果我启用“禁用语言扩展”(/Za)标志,那么您的两个代码示例都将使用VS2015 Update 1生成预期结果。也就是说,第一个编译,第二个不编译。
I'm not sure which extension in particular is interfering here, though. I found this MSDN page: Microsoft Extensions to C and C++, but it does not appear to be complete - for example, binding a non-const T& to an rvalue is not mentioned.
不过,我不确定具体是哪个扩展影响了这里。我找到了这个MSDN页面:对C和c++的Microsoft扩展,但它似乎并不完整——例如,没有提到将非const t&a绑定到rvalue。
#2
5
I have not been able to find any references that documents that the Visual C++ implementation intentionally deviates from the standard in this regard.
我没有找到任何参考文献,证明Visual c++实现在这方面故意偏离了标准。
Here you go: Compiler Warning (level 1) C4928. The message is
这里是:编译器警告(第一级)C4928。消息是
illegal copy-initialization; more than one user-defined conversion has been implicitly applied
非法copy-initialization;已经隐式地应用了多个用户定义的转换
It also says this:
它还说:
The compiler executed the code in all such routines.
编译器在所有这些例程中执行代码。
So there's a de facto language extension that Microsoft has only barely documented.
所以事实上有一种语言扩展,微软几乎没有记录。
You can use command line argument /we4928
to convert the warning into an error, effectively removing this single extension. See here for these arguments.
您可以使用命令行参数/we4928将警告转换为错误,有效地删除此单个扩展。看看这些论点。
#1
12
Both your code samples produce the expected result with VS2015 Update 1, if I enable the "Disable Language Extensions" (/Za
) flag. That is, the first one compiles, the second one does not.
如果我启用“禁用语言扩展”(/Za)标志,那么您的两个代码示例都将使用VS2015 Update 1生成预期结果。也就是说,第一个编译,第二个不编译。
I'm not sure which extension in particular is interfering here, though. I found this MSDN page: Microsoft Extensions to C and C++, but it does not appear to be complete - for example, binding a non-const T& to an rvalue is not mentioned.
不过,我不确定具体是哪个扩展影响了这里。我找到了这个MSDN页面:对C和c++的Microsoft扩展,但它似乎并不完整——例如,没有提到将非const t&a绑定到rvalue。
#2
5
I have not been able to find any references that documents that the Visual C++ implementation intentionally deviates from the standard in this regard.
我没有找到任何参考文献,证明Visual c++实现在这方面故意偏离了标准。
Here you go: Compiler Warning (level 1) C4928. The message is
这里是:编译器警告(第一级)C4928。消息是
illegal copy-initialization; more than one user-defined conversion has been implicitly applied
非法copy-initialization;已经隐式地应用了多个用户定义的转换
It also says this:
它还说:
The compiler executed the code in all such routines.
编译器在所有这些例程中执行代码。
So there's a de facto language extension that Microsoft has only barely documented.
所以事实上有一种语言扩展,微软几乎没有记录。
You can use command line argument /we4928
to convert the warning into an error, effectively removing this single extension. See here for these arguments.
您可以使用命令行参数/we4928将警告转换为错误,有效地删除此单个扩展。看看这些论点。