转换在Visual Studio 2015中不明确,但与clang不同

时间:2015-12-08 20:24:45

标签: c++ visual-studio-2015 clang

以下代码(在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 ++实现在这方面有意偏离标准的文档的引用。

这是一个众所周知的问题吗?

2 个答案:

答案 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