以下代码(在googlemock项目中找到的代码的简化版本)无法在Visual Studio 2015 Update 1中编译,但它在clang [Apple LLVM版本7.0.0(clang-700.1.76)]上编译。 / p>
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;
}
错误发生在赋值语句
Matcher<ConvertibleFromAny> m = em;
,错误消息是
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
我可以天真地看到成员电话
之间存在歧义EqMatcher<ConvertibleFromAny>::operator Matcher<ConvertibleFromAny>()
和概念上类似于
的初始化Matcher<ConvertibleFromAny> m(ConvertibleFromAny<EqMatcher<ConvertibleFromAny>>(em))
我的猜测是clang排除了第二种选择。
编辑:受T.C。的评论启发,我测试了以下内容:struct A
{
};
struct X
{
X(const A&);
};
struct B
{
B(const X&);
};
int main()
{
A a;
B b = a;
}
它与VS 2015编译,但不与clang编译。我无法找到任何关于Visual C ++实现在这方面有意偏离标准的文档的引用。
这是一个众所周知的问题吗?
答案 0 :(得分:12)
如果我启用&#34;禁用语言扩展程序&#34;那么您的代码示例都会在VS2015 Update 1中生成预期结果。 (GRANT EXECUTE ON dbo.StoredProcNameHere TO UsernameRunningreports
GO
)标志。也就是说,第一个编译,第二个不编译。
我不确定哪个扩展特别干扰了这里。 我找到了这个MSDN页面:Microsoft Extensions to C and C++,但它似乎并不完整 - 例如,绑定非const T&amp;没有提到rvalue。
答案 1 :(得分:5)
我一直无法找到任何文件证明 Visual C ++实现故意偏离标准 这方面。
在这里:Compiler Warning (level 1) C4928。消息是
非法复制初始化;隐式应用了多个用户定义的转换
它也这样说:
编译器在所有这些例程中执行了代码。
所以有一个事实上的语言扩展,微软几乎没有记录。
您可以使用命令行参数/we4928
将警告转换为错误,从而有效地删除此单个扩展名。有关这些参数,请参阅here。