转换为`const Y'不适用于clang上的`R&`` [英] Conversion to `const Y` not applicable for `R&&` on clang

查看:308
本文介绍了转换为`const Y'不适用于clang上的`R&``的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码使用 g ++(GCC)4.7.1 20120721 编译良好,但
失败,最近生成 clang版本3.2 (trunk)

  struct Y {}; 

struct X {
operator const Y()const {return Y(); }
};

void f(Y& y){}

int main()
{
f(X());
return 0;
}

将转换运算符更改为



在这种情况下,哪个编译器实际上是标准兼容的?



请求的逐字错误:

  bla.cpp:14:5:错误:没有可行的转换从'X'到'Y'
f(X());
^ ~~
bla.cpp:1:8:注意:候选构造函数(隐式复制构造函数)不可行:没有已知的从'X'到
的转换const Y&对于第一个参数
struct Y {
^
bla.cpp:1:8:note:候选构造函数(隐式移动构造函数)不可行:没有已知的从'X' $ b'Y&&'for 1st argument
struct Y {
^
bla.cpp:6:3:注意:候选函数
operator const Y {return Y(); }
^
bla.cpp:10:12:注意:这里传递参数到参数'y'
void f(Y& y){}
^

编辑:很遗憾,即使添加过载

  void f(const Y&){} 

仍然使ang选择右值引用重载,所以这
打破了用于编译精细的现有代码,例如与标准的
容器。

解决方案

我相信ang是正确的。将参数传递给 f(Y&&)需要两个转换步骤,第一个是您的运算符const Y(),第二个是 Y 的副本构造函数。我认为这两者都被视为用户定义的转换,并且都是隐式的,这违反了隐式转换序列仅包括一个用户定义的转换的原理。



返回目的const value?对返回 const T 的语义有一些有趣的见解。



<如果我尝试添加一个重载 void f(const Y& y)作为编辑的问题现在做,cl行为很奇怪。仍然抱怨无法将 X 转换为 Y ,甚至不列出重载 f(const Y& y)。但是一旦我改变了重载,通过值来取 Y ,即写 void f(const Y y)关于 f 不明确的呼叫。



这是使用XCode 4.5的clang,报告 Apple clang 4.1版(标签/ Apple / clang-421.11.66)(基于LLVM 3.1svn)。如果你可以用香草can再现,你应该在clang邮件列表上报告 - 肯定似乎有一个错误潜伏在某处 ...


The following code compiles fine with g++ (GCC) 4.7.1 20120721, but fails with a recently build clang version 3.2 (trunk).

struct Y {};

struct X {
  operator const Y() const { return Y(); }
};

void f(Y&& y) {}

int main()
{
  f(X());
  return 0;
}

Changing the conversion operator to operator Y() const is sufficient to make the code compile on both compilers.

Which compiler is actually standard compliant in this case? What does the standard actually say about this?

The verbatim error as requested:

bla.cpp:14:5: error: no viable conversion from 'X' to 'Y'
  f(X());
    ^~~
bla.cpp:1:8: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'X' to
      'const Y &' for 1st argument
struct Y {
       ^
bla.cpp:1:8: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'X' to
      'Y &&' for 1st argument
struct Y {
       ^
bla.cpp:6:3: note: candidate function
  operator const Y() const { return Y(); }
  ^
bla.cpp:10:12: note: passing argument to parameter 'y' here
void f(Y&& y) {}
       ^

EDIT: Unfortunately even adding the overload

void f(const Y&) {}

still makes clang choose the rvalue reference overload and so this breaks existing code that used to compile fine, e.g. with standard containers.

解决方案

I believe clang is right to reject this. Passing the argument to f(Y&&) requires two conversion steps, the first being your operator const Y() and the second being Y's copy constructor. Both count as user-defined conversions, I think, and both are implicit, which violates the principle that an implicit conversion sequence only includes one user-defined conversion.

This Purpose of returning by const value? contains some interesting insights into the semantics of returning a const T.

Hm, if I try adding an overload void f(const Y&y) as the edited question now does, clang behaves pretty strangly. It still complains about being unable to convert X to Y, and doesn't even list the overload f(const Y& y) in its diagnostic. But once I change the overload to take Y by value, i.e. write void f(const Y y), it complains about the call to f being ambiguous.

This is with XCode 4.5's clang which reports Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn). If you can reproduce this with a vanilla clang, you should probably report this on the clang mailing list - sure seems to there's a bug lurking there somewhere...

这篇关于转换为`const Y'不适用于clang上的`R&amp;``的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆