2016-07-09 1 views
3

Существует что-то не так с тем, как оператор преобразования ведет себя в следующем коде:оператор преобразования обходит конструктор производного типа и пропускает копию-инициализацию базового типа?

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):

test.cpp:24:7: error: use of deleted function 'A::A(const A&)' 
    foo(c); //2) Not Ok 
    ^

Так что вопрос: почему в аду он хочет скопировать-инициализировать A? Примечание. B объявляет свой собственный конструктор копирования. Я бы хотел, чтобы этот вызов 1), который преуспел, идентичен 2), но, видимо, это не так?

О практической проблеме, которую я пытаюсь решить: в классе C я хотел предоставить преобразование в сторонний класс A, который запрещает копирование. Идея состояла в том, чтобы вернуть прокси B: A, который добавит семантику перемещения поверх A. Есть ли другой способ определить оператор преобразования, чтобы получить A в стеке, подчиняясь его политике без копирования.

+0

О, дерьмо, я выяснил, что это ошибки в gcc 4.8.3 и VS Nov_2013, но работает нормально с gcc 4.9.3 и clang-7.0.2. Поскольку, по-видимому, это проблема с компилятором, я должен ответить на вопрос? –

+0

Нет, это правильный вопрос. Нет ничего плохого в вопросе, который оказывается ошибкой компилятора. –

ответ

1

В C++ 98, когда ссылка на константу инициализируется rvalue, компилятору разрешено создавать временную копию rvalue. Для этого может потребоваться наличие конструктора копирования.

Несмотря на то, что вы не компилируете в режиме C++ 98, сообщение об ошибке, которое вы наблюдаете, безусловно, выглядит как затяжной остаток этого устаревшего требования. В вашем случае ссылка const A & инициализируется значением r B.

Код, кажется, компилируется с GCC (http://coliru.stacked-crooked.com/a/0d58fd31a0b50cf5), что означает, что то, что вы наблюдаете, скорее всего, является ошибкой в ​​вашем компиляторе. Я просто предлагаю возможное обоснование этой ошибки.

0

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. 

Я не вижу ничего плохого с показанным кодом. Я считаю, что это ошибка в любом компиляторе, который вы используете.

Смежные вопросы