Основная проблема заключается в том, что
g(getx()); //error
является логической ошибкой: g
модифицирует результат getx()
, но вы не имеете возможности исследовать измененный объект. Если g
не нужно было изменять свой параметр, тогда он не требовал бы ссылки lvalue, он мог бы взять параметр по значению или по ссылке const.
const X& x = getx(); // OK
действителен, потому что вы иногда нужно повторно использовать результат выражения, и довольно ясно, что вы имеете дело с временным объектом.
Однако невозможно сделать
X& x = getx(); // error
действительным без делая g(getx())
действительным, что и пытались избежать в первую очередь разработчиками языка.
g(getx().ref()); //OK
справедливо, поскольку методы знают только о константе this
, они не не знаю, вызваны ли они lvalue или rvalue.
Как всегда в C ++ у вас есть обходное правило для этого правила, но вы должны сообщить компилятору, что знаете, что вы делаете, будучи явным:
g(const_cast<x&>(getX()));