Каков наилучший способ привязать ссылку на rvalue к какому-либо объекту или его временной копии?
A &&var_or_dummy = modify? static_cast<A&&>( my_A )
: static_cast<A&&>( static_cast<A>( my_A ) );
(Этот код не работает в моем недавнем GCC 4.6… Я его помнюработал раньше, но теперь он всегда возвращает копию.)
В первой строке static_cast
преобразует my_A
из lvalue в xvalue.(C ++ 0x §5.2.9 / 1-3) Внутренний static_cast
во второй строке выполняет преобразование lvalue в rvalue, а внешний получает значение xvalue из этого prvalue.
Это появляетсябыть поддержанным, потому что именованная ссылка условно связана с временной согласно §12.2 / 5.Тот же трюк работает в C ++ 03 со ссылкой const
.
Я также могу написать то же самое менее подробно:
A &&var_or_dummy = modify? std::move( my_A )
: static_cast<A&&>( A( my_A ) );
Теперь это намного короче.Первая аббревиатура сомнительна: move
должен сигнализировать о том, что с объектом что-то происходит, а не просто перестановка lvalue-to-xvalue-to-lvalue.Заблуждение, что move
нельзя использовать после :
, потому что вызов функции прервал бы временную привязку к ссылке.Синтаксис A(my_A)
, возможно, более понятен, чем static_cast
, но технически он эквивалентен приведению в стиле C.
Я также могу пройти весь путь и написать его полностью в приведениях в стиле C:
A &&var_or_dummy = modify? (A&&)( my_A ) : (A&&)( A( my_A ) );
В конце концов, если это будет идиома, это должно быть удобно, и static_cast
на самом деле не защищает меня от чего бы то ни было - реальная опасность заключается в том, что нельзя напрямую связываться с my_A
в случае true
.
С другой стороны, это легко определяется тем, что имя типа повторяется три раза.Если бы A
был заменен большим, некрасивым идентификатором шаблона, я бы действительно хотел настоящий ярлык.
(Обратите внимание, что V
оценивается только один раз, несмотря на то, что он появляется пять раз:)
#define VAR_OR_DUMMY( C, V ) ( (C)? \
static_cast< typename std::remove_reference< decltype(V) >::type && >( V ) \
: static_cast< typename std::remove_reference< decltype(V) >::type && > ( \
static_cast< typename std::remove_reference< decltype(V) >::type >( V ) ) )
Хаки, как и макросы, я думаю, что это лучшая альтернатива.Это немного опасно, потому что возвращает xvalue, поэтому его не следует использовать вне инициализации ссылки.
Должно быть что-то, о чем я не подумал ... предложения?