Предыстория и предыдущий поиск
Я ищу элегантный способ обратной обработки по контейнеру (например, std :: vector) с использованием цикла for-loop на С++ 14. В поисках решения я нашел этот Q/A. В основном это говорит мне, что это не часть стандартной библиотеки, и я должен использовать boost или реализовать адаптер самостоятельно. Я не хочу использовать boost, поэтому теперь я ищу лучшую собственную реализацию.
Помимо предложений, приведенных в ранее упомянутом Q/A, я также нашел эту реализацию и этот блог по этой теме. Большинство реализаций довольно схожи и кажутся вполне приличными. Однако у всех их есть ловушка: как указано в этом комментарии, вы можете оказаться в обмотанной ссылке, если вы вызываете обратный адаптер с временным объектом:
for (const auto& v : reverse_iterate(getContainer()))
Что касается проблемы с временным объектом в цикле на основе диапазона, этот ответ действительно помог мне понять. Но что мы можем сделать, чтобы предотвратить свисающую ссылку?
Мое решение
Исходя из этого фона, я ищу реализацию, которая избавится от этой ловушки. В следующей реализации я использую дополнительную rvalue-reference rx_
чтобы продлить время жизни моего входного параметра iff reverse_iterate
вызывается с ссылкой rvalue.
EDIT: Не используйте это решение. Это неправильно, как указано в принятом решении.
template <typename T>
class reverse_range
{
T &&rx_; // rvalue-reference to prolong livetime of temporary object
T &x_; // reference to container
public:
explicit reverse_range(T &x) : rx_(T{}), x_(x) {}
explicit reverse_range(T &&rx) : rx_(std::move(rx)), x_(rx_) {}
auto begin() const -> decltype(this->x_.rbegin())
{
return x_.rbegin();
}
auto end() const -> decltype(this->x_.rend())
{
return x_.rend();
}
};
template <typename T>
reverse_range<T> reverse_iterate(T &x)
{
return reverse_range<T>(x);
}
template <typename T>
reverse_range<T> reverse_iterate(T &&rx)
{
return reverse_range<T>(std::move(rx));
}
Очевидно, мы генерируем немного накладных расходов на создание неиспользуемого пустого объекта-контейнера в конструкторе lvalue, но я думаю, что это не так уж плохо. Кроме того, можно было бы избавиться от этого, предоставив два класса: reverse_range_lvalue
и reverse_range_rvalue
, каждый из которых обеспечивает реализацию для одного из типов параметров...
Вопросы
Будет ли вышеупомянутое расширение решить проблему оборванных ссылок или мне что-то не хватает?
Есть ли у вас какие-либо намеки на дальнейшие проблемы с моим кодом?
Есть ли идеи для решения этой проблемы в С++ 14 или любой другой (будущей) версии?