Boost logo

Boost :

Subject: Re: [boost] [Range] New I/O functions for ranges
From: Indiana (indi.in.the.wired_at_[hidden])
Date: 2014-11-25 13:49:18


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.

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.
> 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
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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk