On 14-11-24 11:03 AM, Nat Goodspeed wrote:
A third potential option would be to restrict the API based on BOOST_NO_CXX11_RVALUE_REFERENCES. That is, when that macro is set, make write_all() accept non-const reference. This could potentially allow *some* use of the library even with C++03 code -- say, with a local vector -- without loss of safety. I've actually been working on a different strategy - an entirely separate interface for C++98 support.
I agree with the above. I simply suggest that even in C++03, you could potentially support a safe subset of desirable use cases. I agree. The functionality offered by write_all (et al) is not just syntactic sugar hiding a for loop - it also handles formatting and makes error checking easy (and, in some cases, practical when it wasn't otherwise). I could probably have submitted a first draft of this
The problem with the C++11 interface is that while you get a really nice interface, the actual write operation may be deferred for quite some time. That's where the problem comes up in C++98: without rvalue references to capture temporaries, your temporary iterable object may have died in the meantime. So instead of the C++11 interface that allows inlining: auto p = write_all(v, ", "); cout << "{ " << p << " }"; // now query p for information about the write The interface I'm putting together for C++98 support is a separate function: cout << "{ "; write_all_result_t r = write_all_compat(cout, v, ", "); cout << " }"; // now query r for information about the write The C++98 compatibility interface is clunkier, but on the other hand, since the iterable is used immediately you don't have to worry about it expiring prematurely. In C++98 - or rather, when BOOST_NO_CXX11_RVALUE_REFERENCES is not defined, the C++11 interface is simply not available. What I've been mucking around with is the question of whether "write_all_compat" should be *just* a compatibility interface for C++98, or an actual first-class alternative interface. It's clunkier than the original interface, but on the other hand it's got kind of a functional flavour. The motivating case I've been musing over is doing background writes: // With the C++11 interface: auto f = async([&o, &v] { return o << write_all(v, ", "); }); // With the C++98 interface (in C++11, of course): auto f = async(write_all_compat, ref(o), cref(v), ", "); Personally, I find the second not only shorter (and it might be even shorter if the function is given a better name, like "write_all_to" or "do_write_all"), but clearer. library a couple weeks ago, if I'd ignored C++98 support, but I consider it important enough to spend some time working on. Whatever form it takes, this library will *definitely* offer C++98 support. Indi