Единственная разница между ref
и const ref
заключается в том, что const ref
- это const
, а ref
- нет.Оба должны принимать переменную.Ни один не может занять временное.Это отличается от C ++, где const T&
будет принимать любое значение типа T
, включая временные.
opBinary
не может возвращать либо ref
, либо const ref
, потому что нет переменной для возврата.Это создает временный.То же самое касается Create
.И создание локальной переменной со значением, которое вы хотите вернуть, также не помогает, потому что вы не можете вернуть ссылку на локальную переменную.В конечном итоге он ссылается на переменную, которой больше не существует.
Здесь нужно добавить еще одну перегрузку opEquals
:
bool opEquals(CustomReal x) const
{
return value == x.value; // just for fun
}
С этим ваш кодбудет компилироваться.
Я хотел бы отметить, что текущая ситуация с opEquals
требует , что нужно немного сгладить.Вы заметите, что если у вас есть только перегрузка для opEquals
, которую я вам дал, а не та, которая у вас есть в данный момент, код не скомпилируется, и вы получите ошибку, подобную этой:
prog.d(15): Error: function prog.CustomReal.opEquals type signature should be const bool(ref const(CustomReal)) not const bool(CustomReal x)
Компилятор в настоящее время слишком требователен к точной сигнатуре opEquals
для структур (некоторые другие функции, такие как toString
, имеют аналогичные проблемы).Это известная проблема, которая, вероятно, будет решена в ближайшем будущем.Однако пока просто объявите обе перегрузки opEquals
.Если вы сравните CustomReal
с переменной, то будет использоваться версия const ref
, а если вы сравните CustomReal
с временной, то будет использоваться другая версия.Но если у вас есть оба, с вами все будет в порядке.
Теперь, почему
assert(a == CustomReal(123.123456));
работает, а
assert(a == Create());
нет, я не уверен,Я бы на самом деле ожидал, что оба из них потерпят неудачу, учитывая, что const ref
не может занять временное значение, но по какой-то причине компилятор принимает его здесь - это, вероятно, связано с тем, как он обрабатывает opEquals
спец.Несмотря на это, как я уже сказал, есть некоторые проблемы с opEquals
и структурами, которые необходимо устранить, и, надеюсь, это произойдет в ближайшее время.Но в то же время объявление обеих перегрузок opEquals
, кажется, делает свое дело.
EDIT: Похоже, что причина того, что
assert(a == CustomReal(123.123456));
работает, и
assert(a == Create());
не из-за того факта (по причинам, которые я не понимаю), структурный литерал считается lvalue, тогда как возвращаемое значение функции, которая не является ref
, равно (неудивительно)))С ним связано пара из отчетов об ошибках , утверждающих, что структурные литералы должны быть значениями r, но, очевидно, они являются lvalues по замыслу (что сбивает меня с толку).В любом случае, именно поэтому функция, которая принимает const ref
, работает со структурным литералом, но не с возвращаемым значением функции.