c++11 - clang++失败,但g++成功在赋值中使用强制转换为const-unrelated-type运算符

标签 c++11 g++ language-lawyer clang++ conversion-operator

这是一个简短的示例,再现了“no viable conversion” with lemon for clang but valid for g++在编译器行为上的差异。

#include <iostream>

struct A { 
    int i; 
};

#ifndef UNSCREW_CLANG
using cast_type = const A;
#else 
using cast_type = A;
#endif

struct B {
    operator cast_type () const {
        return A{i};
    }
    int i;
}; 

int main () { 
    A a{0};
    B b{1};

#ifndef CLANG_WORKAROUND
    a = b;
#else    
    a = b.operator cast_type ();
#endif    

    std::cout << a.i << std::endl;    

    return EXIT_SUCCESS;
}

在bolt的live

g++(4.9,5.2)会以静默方式进行编译;而clang++(3.5,3.7)编译它

如果
using cast_type = A;

或者
using cast_type = const A;
// [...] 
a = b.operator cast_type ();

被使用,
,但默认值不是
using cast_type = const A;
// [...] 
a = b; 

在这种情况下,clang++(3.5)会怪a = b:
testling.c++:25:9: error: no viable conversion from 'B' to 'A'
    a = b;
        ^
testling.c++:3:8: note: candidate constructor (the implicit copy constructor) 
not viable:
      no known conversion from 'B' to 'const A &' for 1st argument
struct A { 
       ^
testling.c++:3:8: note: candidate constructor (the implicit move constructor) 
not viable:
      no known conversion from 'B' to 'A &&' for 1st argument
struct A { 
       ^
testling.c++:14:5: note: candidate function
    operator cast_type () const {
    ^
testling.c++:3:8: note: passing argument to parameter here
struct A { 

关于2011¹标准:clang++是否可以拒绝默认代码,或者g++是否可以接受默认代码?

注意::这是,而不是,是关于const上的cast_type限定词是否有意义的问题。这是关于哪个编译器工作符合标准的,并且仅关于那个

¹2014年应该不会有所作为。

编辑:

请避免使用通用c++标记重新标记。
我首先想知道哪种行为符合2011年标准,并且暂时将委员会的奉献not to break existing (< 2011) code保留在ansatz之内。

最佳答案

因此,此clang错误报告rvalue overload hides the const lvalue one? 似乎涵盖了此示例,该示例具有以下示例:

struct A{};
struct B{operator const A()const;};
void f(A const&);
#ifdef ERR
void f(A&&);
#endif
int main(){
  B a;
  f(a);
}

失败,并显示与OP的代码相同的错误。理查德·史密斯(Richard Smith)最后说:

Update: we're correct to choose 'f(A&&)', but we're wrong to reject the initialization of the parameter. Further reduced:

  struct A {};
  struct B { operator const A(); } b;
  A &&a = b;

Here, [dcl.init.ref]p5 bullet 2 bullet 1 bullet 2 does not apply, because [over.match.ref]p1 finds no candidate conversion functions, because "A" is not reference-compatible with "const A". So we fall into [dcl.init.ref]p5 bullet 2 bullet 2, and copy-initialize a temporary of type A from 'b', and bind the reference to that. I'm not sure where in that process we go wrong.



但由于defect report 1604之后又返回了另一条评论:

DR1604 changed the rules so that

 A &&a = b;

is now ill-formed. So we're now correct to reject the initialization. But this is still a terrible answer; I've prodded CWG again. We should probably discard f(A&&) during overload resolution.



因此,似乎clang在今天基于标准语言在技术上做对了,但是它可能会发生变化,因为至少从clang团队看来这是正确的结果。因此,大概这将导致缺陷报告,我们必须等到问题解决后才能得出最终结论。

更新

好像defect report 2077是基于此问题提交的。

关于c++11 - clang++失败,但g++成功在赋值中使用强制转换为const-unrelated-type运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33673158/

相关文章:

绑定(bind)函数中的 C++ socketio 段错误

c++ - 覆盖默认的未处理异常行为

c++11 - 移动构造函数和 const 成员变量

c++ - 使用 &front() 修改 std::string 中的底层字符数组

c++ - C++11标准中 `top-level cv-qualifiers`的定义在哪里?

c++ - 'auto t = new decltype(nullptr)' 是做什么的?

c++ - 引用/initializer_list 的生命周期

Qt 应用程序严重失败

c++ - G++ 编译器对非交换操作的优化程度

java - Java 外来标识符的状态