This answer does a great job at answering my question, but I thought I'd supply a more generic solution to the problem of ensuring the object output to an ostream_joiner
takes no dangling references, one that uses a lambda to capture those references:
#include <type_traits>
#include <ostream>
template<typename F>
class put_invocation_t {
public:
constexpr put_invocation_t(F const& f) : f(f) {}
constexpr put_invocation_t(F&& f) : f(std::move(f)) {}
template<class charT, class traits>
friend std::basic_ostream<charT, traits>& operator<<(
std::basic_ostream<charT, traits>& os, put_invocation_t const& pi
) {
return pi.f(os);
}
private:
F f;
};
// or use a deduction guide in C++17
template<typename F>
put_invocation_t<std::decay_t<F>> put_invocation(F&& f) {
return put_invocation_t<std::decay_t<F>>(std::forward<F>(f));
}
Used as
std::transform(
std::begin(values), std::end(values),
std::experimental::make_ostream_joiner(std::cout, ", "),
[](long double v) {
return put_invocation([=](auto& os) -> auto& {
return os << std::put_money(v + 1);
});
}
);
This has the bonus of also scaling to outputing multiple values, by using something like the following within the transform
:
return put_invocation([=](auto& os) -> auto& {
return os << "Value is: " << std::put_money(v + 1);
});