Шаблоны выражений и ранжирование на основе в C ++ 11 - PullRequest
9 голосов
/ 01 марта 2012

Насколько я понимаю, шаблоны выражений будут разбиваться на ранжированные в C ++ 11, так как for (auto x : expr) содержит неявное auto&& __range = expr, и это приведет к висящим ссылкам.

Есть ли способ создать классы шаблонов выражений, чтобы они либо вели себя корректно с использованием ранжирования на основе, либо, по крайней мере, выдавали ошибку компиляции?

В принципе, я бы хотел предотвратить возможность правильной компиляции шаблонов выражений.но потерпеть неудачу во время выполнения из-за висячих ссылок.Я не возражаю против необходимости оборачивать шаблоны выражений во что-то перед их использованием в ранжированной основе, пока не будет никаких тихих ошибок времени выполнения, если пользователь забудет обернуть шаблоны выражений.

Ответы [ 2 ]

6 голосов
/ 01 марта 2012

Как правило, вы ничего не можете с этим поделать.Если вы задаете выражение в качестве диапазона, оно должно разрешиться до того, что будет действительным после инициализации оператора for.И нет никакого способа обнаружить во время компиляции, что какой-то конкретный тип был выведен с помощью auto.

. Было бы лучше сделать вашу систему выражений более ориентированной на перемещение, чтобы она не содержалаРекомендации.Это даст гораздо более безопасный результат с auto, чем попытка сохранить ссылки на потенциально мертвые вещи.Если вас беспокоит копирование неподвижных типов, просто живите с этим.

2 голосов
/ 07 марта 2012

Есть несколько вариантов, которые я могу придумать, каждый со своим уродством.

Один очевидный вариант - использовать указатели (вероятно, unique_ptr) вместо ссылок.Конечно, чтобы это работало, требуется либо выделение из кучи, либо пользовательские распределители.Я думаю, что с хорошим распределителем у этого подхода есть некоторые достоинства.С другой стороны, перегрузка оператора будет просто неприятной.

Другой подход - хранить подвыражения по значению, а не по константной ссылке.Эффективность этого подхода очень зависит от компилятора, но, поскольку вы в основном имеете дело с кучей временных файлов, я бы предположил, что современные компиляторы могут оптимизировать копии (или, по крайней мере, много копий).

Последний подход позволяет сохранить ту же структуру в вашем коде, но заставляет пользователя оценивать выражение.Это требует, чтобы у вас был только один итеративный тип, который является базовым типом выражения (скажем, std::vector<int>).Ни один из классов выражений не должен иметь методы или функции begin и end, определенные для них, а должен быть просто конвертируемым в базовый тип.Таким образом, код, подобный for(auto x : expr), потерпит неудачу во время компиляции (поскольку expr не повторяется), но запись for(auto x : static_cast<vector<int>>(expr)) работает, потому что выражение уже вычислено.

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

...