У меня есть класс, который накапливает информацию о наборе объектов и может действовать как функтор или выходной итератор. Это позволяет мне делать такие вещи, как:
std::vector<Foo> v;
Foo const x = std::for_each(v.begin(), v.end(), Joiner<Foo>());
и
Foo const x = std::copy(v.begin(), v.end(), Joiner<Foo>());
Теперь, теоретически, компилятор должен иметь возможность использовать копирование и оптимизацию возвращаемых значений, чтобы только один Joiner
объект должен быть создан. На практике, однако, функция создает копию, на которой будет работать, а затем копирует ее обратно в результат даже в полностью оптимизированных сборках.
Если я создаю функтор как lvalue, компилятор создает две дополнительные копии вместо одной:
Joiner<Foo> joiner;
Foo const x = std::copy(v.begin(), v.end(), joiner);
Если я неуклюже заставляю тип шаблона ссылаться на ссылку, но затем все равно копирует его и возвращает оборванную ссылку на временную копию (теперь уничтоженную):
x = std::copy<Container::const_iterator, Joiner<Foo>&>(...));
Я могу сделать копии дешевыми, используя ссылку на состояние, а не само состояние в функторе в стиле std::inserter
, что приведет к чему-то вроде этого:
Foo output;
std::copy(v.begin(), v.end(), Joiner<Foo>(output));
Но это делает невозможным использование "функционального" стиля неизменяемых объектов, и, как правило, это не так приятно.
Есть ли способ побудить компилятор исключить временные копии или заставить его полностью пройти ссылку и вернуть эту же ссылку?