Обходные пути для отсутствия ссылок rvalue на эту функцию

У меня есть класс контейнера прокси вокруг подвижного объекта, и я хочу, чтобы прокси мог неявно выдавать ссылку rvalue на базовый объект, но только тогда, когда сам прокси перемещается.

Я считаю, что смогу реализовать это поведение согласно предложению n2439 " Расширение семантики перемещения до * this ", но это еще не доступно в версии gcc и не будет в ближайшее время.

Приведенный ниже код - это то, к чему я в конечном итоге стремлюсь, но в настоящее время это невозможно. Существуют ли какие-либо эквивалентные обходные пути, пока мне не будет доступна эта функция?

template< class T >
struct movable_proxy {
    operator T&&() && {
        return std::move(value);
    }

    operator const T&() const& {
        return value;
    }

private:
    T value;
};

person boycy    schedule 28.01.2013    source источник
comment
Я думаю, что самое близкое, что вы сможете получить, - это функция, которая выполняет преобразование явно, а не имеет оператора преобразования, поэтому вам нужно будет сказать convert_proxy(p), который перегружен для rvalues ​​и lvalues, чтобы вернуть либо T&&, либо const T& .. . но это делает использование прокси непрозрачным, что, вероятно, не то, что вы хотите   -  person Jonathan Wakely    schedule 28.01.2013
comment
На самом деле это не так: хотя он работоспособен, он связывает клиентский код с прокси. Конструктор преобразования обернутого типа тоже будет работать, но он связывает с ним обернутый тип ...   -  person boycy    schedule 28.01.2013
comment
О, предложенный синтаксис отличный.   -  person Lightness Races in Orbit    schedule 28.01.2013
comment
Э ... потенциально дурацкая идея: будет ли завершенная специализация std :: move ‹movable_proxy ‹xyz›› для возврата xyz && вместо movable_proxy ‹xyz› && совершенно безумной?   -  person boycy    schedule 28.01.2013
comment
Мне любопытно. Извините за непонимание, но я бы хотел его получить. Если вы удалите недавно предложенные модификаторы && и &, что именно вам не хватает?   -  person Andy Prowl    schedule 28.01.2013
comment
Для записи: попробуйте clang 2.9.   -  person Lightness Races in Orbit    schedule 28.01.2013
comment
@AndyProwl: в этом случае прокси может конвертировать как в T const&, так и в T&&, независимо от категории значения самого прокси. Я думаю, OP хочет, чтобы proxy&& преобразовали в T&& и proxy& в T const&.   -  person Nawaz    schedule 28.01.2013
comment
@boycy, разве ты не хочешь специализироваться std::forward, а не std::move? Последний всегда преобразуется в rvalue, даже если источник не был rvalue. И это помогает только в том случае, если прокси-объект явно перемещается / перенаправляется, а не если он просто возвращается как rvalue   -  person Jonathan Wakely    schedule 28.01.2013
comment
@JonathanWakely: Как std::forward вообще имеет смысл в этом контексте, если T не является выводимым типом?   -  person Nawaz    schedule 28.01.2013
comment
@Nawaz: поэтому формулировку только тогда, когда сам прокси является подвижным, следует понимать как только тогда, когда объект прокси перемещается, так ли это?   -  person Andy Prowl    schedule 28.01.2013
comment
@AndyProwl: Думаю, да. :-)   -  person Nawaz    schedule 28.01.2013
comment
Кто-нибудь знает, почему эта функция не вошла в gcc?   -  person Omnifarious    schedule 28.01.2013
comment
Бесстыдный плагин для неосведомленных: Что такое ссылка rvalue для * этого?   -  person Xeo    schedule 28.01.2013
comment
@Xeo: семь комментариев вверх!   -  person Lightness Races in Orbit    schedule 28.01.2013
comment
@ Non-StopTimeTravel мой v3.0 лязгает с изобилием ошибок при включении стандартных заголовков :-(   -  person boycy    schedule 28.01.2013
comment
@JonathanWakely Ах, конечно, моя ошибка.   -  person boycy    schedule 28.01.2013
comment
@AndyProwl - спасибо, отредактировал для уточнения.   -  person boycy    schedule 28.01.2013
comment
@Omnifarious просто потому, что он еще не реализован. Это последняя отсутствующая функция основного языка, но она гораздо менее востребована (или, по моему мнению, нужна), чем лямбда-выражения, ссылки на rvalue и т. Д. Она будет в GCC 4.9, возможно, даже в 4.8.x для некоторых x > 0   -  person Jonathan Wakely    schedule 28.01.2013
comment
@boycy: спасибо, тогда я понимаю и могу оценить вопрос. +1 ;-)   -  person Andy Prowl    schedule 28.01.2013
comment
@JonathanWakely (обреченный на слишком быстрый ответ в обход мозга); специализация std::forward не поможет там, где клиентский код вызывает std::move(movable_proxy<T>&) в ожидании ответа T&&. Я думаю, что для std::forward, чтобы вернуть соответствующую ссылку movable_proxy<T>, т.е. перенаправить прокси в качестве прокси, было бы в общем уместно.   -  person boycy    schedule 28.01.2013
comment
С clang 3.2 он отлично компилируется   -  person Constantin    schedule 20.02.2013
comment
Вы не можете частично специализировать шаблоны функций, и вам не разрешено помещать перегрузки в namespace std - извините, но я не думаю, что есть какой-либо способ прозрачно эмулировать ref-qualifiers. Клиенту нужно делать что-то, кроме простого std::move(o).   -  person Xeo    schedule 04.03.2013
comment
@Xeo: You can't partially specialize function template Разве это ограничение не снято в C ++ 11? Это просто вопрос поддержки компилятора или я ошибаюсь?   -  person Lightness Races in Orbit    schedule 10.04.2013
comment
@LightnessRacesinOrbit Я думаю, что это могло быть рассмотрено в какой-то момент, но никакое ограничение не было снято в C ++ 11. Об этом свидетельствует наличие 14.5.5 частичных специализаций шаблонов классов и отсутствие эквивалента для шаблонов функций, кроме явного запрета (по крайней мере, насколько я могу найти).   -  person boycy    schedule 10.04.2013
comment
@boycy: Вы правы; они были предложены в n1295, но в конечном итоге отклонил (и вполне справедливо, поскольку перегрузка выполняет свою работу).   -  person Lightness Races in Orbit    schedule 10.04.2013
comment
@boycy: (продолжение) (Я не первый, кто думал иначе) ( в тот день, когда Xeo узнала об этом) ( связанные)   -  person Lightness Races in Orbit    schedule 10.04.2013


Ответы (1)


Хороший вопрос. Недавно я попытался написать подобный прокси-класс, но так и не нашел хорошего решения. Лучшее, что я нашел, - это вызов функции-члена при каждом использовании, когда прокси-сервер должен был быть r-значением:

ORef<T> move() {
    return ORef<T>( this->release() );
}

Это изменяет семантику объявления чего-либо как r-значение с std::move(proxy) на proxy.move(), но также дает возможность возврата объекта другого типа (неявно конвертируемого в ваш требуемый тип).

Моя практика кодирования с использованием этого заключалась в том, чтобы всегда передавать прокси-объекты как rvalue, что вынуждает ручную спецификацию семантики (перемещение, общая ссылка, копирование или что-то еще), но это, конечно, делает ошибки использования потенциальной проблемой (например, вызов x.move() перед окончательным использованием x).

person dhardy    schedule 04.03.2013
comment
Спасибо @dhardy; В итоге я получил тот же тип прокси с вызовом «release» и теми же ошибками использования, которые вы упомянули. Жалко, что, похоже, нет обходного пути, но я думаю, что это делает аргумент в пользу необходимого расширения языка хорошим. - person boycy; 11.04.2013