У меня есть класс, который накапливает информацию о наборе объектов и может действовать как функтор или итератор вывода. Это позволяет мне делать такие вещи, как:
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));
Но это делает невозможным использование «функционального» стиля неизменяемых объектов, и, как правило, это не так приятно.
Есть ли какой-нибудь способ побудить компилятор исключить временные копии или сделать так, чтобы он полностью передавал ссылку и возвращал эту же ссылку?