Does put_money hold its argument by value or reference?
The standard ([ext.manip]/6) only defines this specific expression:
out << put_money(mon, intl);
It is unspecified how mon
is stored in the mean time, and it is definitely possible for it to become a dangling reference and be UB.
An "easy" fix is making your own class to know you store the value:
struct money_putter {
long double value;
template<class charT, class traits>
friend std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const money_putter& mon) {
return os << std::put_money(mon.value);
}
};
int main() {
int values[] = {1, 2, 3};
std::transform(
std::begin(values), std::end(values),
std::experimental::make_ostream_joiner(std::cout, ", "),
[](int i) {
return money_putter{i}; // or i + 1
}
);
return 0;
}
You could test it, though this wont tell you anything about whether it is guaranteed, but then as the return type of put_money is not specified, you cannot assume that the returned value does not hold a reference.
...anyhow let's test it:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <experimental/iterator>
int main() {
int i = 42;
std::cout << std::put_money(i) << "\n";
auto x = std::put_money(i);
i = 43;
std::cout << x;
return 0;
}
Output with clang:
42
43
So actually the answer is positive. With clang the returned value does hold a reference and the output is the same with gcc. Hence, yes your code has UB.