Ответ 1
Короткий ответ: Это была ошибка в стандарте, которая исправлена в С++ 14, а g++ 4.9 имеет исправление (задним числом применяется также к режиму С++ 11). Отчет о дефектах 1288
Вот более простой пример:
struct S
{
int x;
S() { } // this causes S to not be an aggregate (otherwise aggregate
// initialization is used instead of list initialization)
};
S x = 5;
S const &y { x } ;
x = 6;
std::cout << y << std::endl; // output : 5
В тексте С++ 11 значение S const &y {x};
не связывает y
с x
; на самом деле смысл состоит в том, чтобы создать временное и связать ссылку на это. Из С++ 11 [dcl.init.ref]/3:
В противном случае, если T является ссылочным типом, временное значение для типа, на которое ссылается T, инициализируется по списку, а ссылка привязана к этому временному. [Примечание. Как обычно, привязка завершится неудачно, и программа будет плохо сформирована, если ссылочный тип является ссылкой lvalue на неконстантный тип. -end note]
Это довольно глупо, ясно, что целью этого кода является привязка y
непосредственно к x
. В С++ 14 текст был изменен:
В противном случае, если в списке инициализаторов есть один элемент типа E, и либо T не является ссылочным типом, либо его ссылочный тип ссылается на E, объект или ссылка инициализируются из этого элемента;
Поскольку тип связан с привязкой к самому себе (или одному из его базовых классов), в моем примере здесь и в вашем фактическом коде, он должен фактически корректно связываться.
Ваше сообщение об ошибке приходит из компилятора, следующего за формулировкой С++ 11, и пытается создать временную ссылку из base
для привязки ссылки; и это терпит неудачу, потому что base
имеет абстрактный тип.