2014-12-15 3 views
5

Приносим извинения, если вопрос не соответствует действительности, но у меня возникают трудности с пониманием того, что здесь происходит.Lvalue decaying to rvalue с автоматической ошибкой

Рассмотрим следующий класс:

struct foo { 
    foo(foo&); 
}; 

Следующая не имеет ошибок:

void func(foo& f) { 
    foo bar{f}; 
} 

Однако, когда я использую авто:

void func(foo& f) { 
    auto bar = foo{f}; 
} 

я получаю (ССАГПЗ):

test.cpp: In function ‘void func(foo&)’: 
test.cpp:6:21: error: no matching function for call to ‘foo::foo(foo)’ 
test.cpp:6:21: note: candidate is: 
test.cpp:2:5: note: foo::foo(foo&) 
test.cpp:2:5: note: no known conversion for argument 1 from ‘foo’ to ‘foo&’ 

(лязг)

test.cpp:6:10: error: no matching constructor for initialization of 'bar' 
    auto bar = foo{f}; 
     ^ ~~~~~~ 
test.cpp:2:5: note: candidate constructor not viable: expects an l-value for 1st argument 
    foo(foo&); 
    ^

Может кто-нибудь, пожалуйста, объясните, почему это ошибка?

Спасибо!

Редактировать: Он работает, если я добавлю конструктор-копию в foo. Однако у меня создалось впечатление, что объявление переменной + явный вызов конструктора с правой стороны синтаксиса «=» обрабатывается специально и не является копией, а скорее прямой инициализацией.

ответ

8
auto bar = foo{f}; 

auto выводится в foo. Впоследствии, ваше определение эквивалентно

foo bar = foo{f}; 

Вы пытаетесь создать объект типа foo, который копия инициализируется с prvalue foo{f}.

Проблема заключается в том, что конструктор копирования foo имеет в качестве своего параметра ссылку на константу lvalue, которую невозможно привязать к rvalue. Кроме того, конструктор перемещения неявно определяется, поскольку у вас есть объявленный пользователем конструктор копирования. Следовательно, нет конструктора, который может принимать foo{f}, и компилятор выдает сообщение об ошибке.

+0

Будет ли компилятор посылать вызов конструктору копирования? У меня создалось впечатление, что компилятор будет рассматривать это как прямую инициализацию. –

+0

Ahh набрав на android медленный, и, похоже, также нет способа удалить ответ –

+0

@RobertMason Компилятор может отказаться от вызова конструктора копирования, который не имеет побочных эффектов, но конструктор копирования все равно должен быть вызван. – Oktalist

3
auto bar = foo{f}; 

Это копирование-инициализация, и по его семантике для этого требуется наличие конструктора копирования. Однако конструктор копирования foo принимает неконстантную ссылку, а ссылка без ссылки не может быть привязана к временному, то есть foo{f}.

Решение заключается в создании конструктора копирования, который принимает константу const, как обычно делают конструкторы копирования.

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

  • Нет связанных вопросов^_^