C++ 转换运算符绕过派生类型的构造函数并跳过复制基类型的初始化?

C++ 转换运算符绕过派生类型的构造函数并跳过复制基类型的初始化?,c++,private,base,conversion-operator,copy-initialization,C++,Private,Base,Conversion Operator,Copy Initialization,以下代码中转换运算符的行为有问题: struct A{ A(){}; A(const A &) = delete; }; struct B : A{ B(const B & x){}; B(int x){}; }; struct C{ operator B() { return B(1); }; }; void foo(const A & x){ }; int main(){ C c;

以下代码中转换运算符的行为有问题:

struct A{
    A(){};
    A(const A &) = delete;
};

struct B : A{
    B(const B & x){};
    B(int x){};
};

struct C{
    operator B() {
        return B(1);
    };
};

void foo(const A & x){
};

int main(){
    C c;
    foo(c.operator B()); //1) Ok    
    foo(c); //2) Not Ok
    return 0;
};
我在通话中出错(2):

所以问题是:它到底为什么要复制初始化?注意,B声明了它自己的副本构造函数。我认为成功的呼叫1)与成功的呼叫2)是相同的,但显然不是


关于我试图解决的实际问题:在C类中,我想提供到第三方a类的转换,这禁止复制。其想法是返回一个代理B:a,该代理将在a上添加移动语义。是否有另一种方法来定义转换运算符,以便在遵守其非复制策略的同时在堆栈上获取a。

gcc 6.1.1编译所示代码时不会出现任何错误:

$ cat t.C
struct A{
    A(){};
    A(const A &) = delete;
};

struct B : A{
    B(const B & x){};
    B(int x){};
};

struct C{
    operator B() {
        return B(1);
    };
};

void foo(const A & x){
};

int main(){
    C c;
    foo(c.operator B()); //1) Ok    
    foo(c); //2) Not Ok
    return 0;
};
$ g++ -g -std=c++1z -o t t.C
$ g++ --version
g++ (GCC) 6.1.1 20160621 (Red Hat 6.1.1-3)
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

我看不出显示的代码有什么问题。我相信这是您正在使用的任何编译器中的一个bug。

在C++98中,当使用右值初始化常量引用时,编译器可以创建右值的临时副本。为此,可能需要存在一个副本构造函数

即使您不是在C++98模式下编译,您观察到的错误消息显然看起来像是过时需求的遗留问题。在您的例子中,
常数a&
引用是用类型为
B
的右值初始化的


代码似乎使用GCC()编译得很好,这意味着您观察到的很可能是编译器中的错误。我只是提出了这个错误背后的一个可能的理由。

哦,废话,我现在在gcc 4.8.3和VS Nov_2013中发现了it错误,但在gcc 4.9.3和clang-7.0.2中工作正常。既然这显然是一个已解决的编译器错误,我应该记下这个问题吗?不,这是一个有效的问题。一个被证明是编译器错误的问题没有错。
$ cat t.C
struct A{
    A(){};
    A(const A &) = delete;
};

struct B : A{
    B(const B & x){};
    B(int x){};
};

struct C{
    operator B() {
        return B(1);
    };
};

void foo(const A & x){
};

int main(){
    C c;
    foo(c.operator B()); //1) Ok    
    foo(c); //2) Not Ok
    return 0;
};
$ g++ -g -std=c++1z -o t t.C
$ g++ --version
g++ (GCC) 6.1.1 20160621 (Red Hat 6.1.1-3)
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.