
As an update of what I've decided on doing: Following the advice of Paul Bristow and Rob Stewart, I have decided to implement the range I/O stuff as a new library with Boost.Range as a dependency. Once it's all up and running and tested and such, I can ask Boost.Range's maintainers whether they'd like to absorb it into Boost.Range or leave it as a separate library (Boost.RangeIO?). Since the whole thing is already (more or less) implemented as a standards proposal, all I had to do, really, was just change the namespace from std to boost, and some other housekeeping stuff. However, I decided to take the opportunity to examine a possibility that a couple people have asked about: whether or not these C++11 facilities can be made available to C++98 code. Looking into that possibility is what's kept me occupied recently. That's where I hit a little snag. It turns out is probably *possible* to implement the facilities in C++98... however, it is impossible to do so in a way that guarantees safety. The problem is that C++98 has no way to prevent you from passing a temporary to a function except by taking the argument by non-const (lvalue) reference, which is too restrictive to help in this case. The following code is perfectly safe in C++11: std::vector<int> get_vec(); // as lvalue std::vector<int> const v = get_vec(); write_all_t<std::vector<int>, std::string> p = write_all(v, ", "); // p contains a reference to v // as rvalue write_all_t<std::vector<int>, std::string> p = write_all(get_vec(), ", "); // p owns the vector But in C++98 it takes a reference to the vector in both cases, which is no good in the second case because the reference is dangling by the end of the expression. The only way to prevent binding to temporaries in C++98 is to take arguments by non-const (lvalue) reference, but if write_all() does that then the "as lvalue" code above won't work. Boost.Move emulation doesn't help in this case, unfortunately. (See the section "Emulation limitations". The relevant subsections are "Template parameters for perfect forwarding" and "Binding of rvalue references to lvalues".) There is no way that the interface or design can be changed to avoid this problem and still remain even marginally useful in practice - the whole concept arose out of an observation of what rvalue references would now allow us to do safely. So my options come down to this: 1) Declare the library C++11-or-better-only. That can be enforced by ensuring that BOOST_NO_CXX11_RVALUE_REFERENCES is not defined, and issuing an error message otherwise. 2) Allow the library to be used in C++98 code, with a warning - either in documentation or, less than ideally, as a diagnostic - about temporaries. Note that there is no way to detect or diagnose if the warning is ignored, deliberately or accidentally, so things that are perfectly legal in C++11 mode can silently introduce undefined behaviour in C++98 mode. I'm leaning toward option 1, mainly for the reason that this is a "syntactic sugar" library. It is not based on any non-portable facilities - anyone can reimplement it on any conforming system - so it doesn't provide "new" capability so much as it makes "old" capability *much* easier. We got by without it for so long in C++98 that it's obviously not the kind of thing people are desperate for - it's more a really nice way to simplify common code, which to me implies it's the kind of thing you will happily use if you can, but it won't cripple your project if you can't. For a facility like that, I don't think it's a worthwhile to introduce potentially undetectable bugs. Better to say "if you can't use it safely, you can't use it - sorry, but just consider this another motivation to move to C++11 when possible", which may irk those developers who can't move to C++11, but c'est la vie. I haven't found any official policy that *disallows* C++11-or-better-only libraries (in fact, I stumbled on someone forking Boost to make it *completely* C++11-or-better-only), and it seems to me that relying on it is no different from a library relying on C++98 features that some compilers never got around to supporting. Obviously, insisting on C++11 just for the sake of doing so would be silly, but in this case the library *needs* a C++11 feature that cannot be emulated or avoided (indeed, safe rvalue reference binding is just about the only C++11 feature that falls into that category) - and the functionality it provides is (IMHO) well worth it. So unless anyone objects, I'm going to go ahead and make this "RangeIO" library require C++11. (Specifically, I'm going to make it require rvalue references - I'm not going to use any more C++11 functionality than is absolutely necessary, so no auto or non-static member initializers, etc.. For example, I will have it use std::initializer_list, but only if BOOST_NO_CXX11_HDR_INITIALIZER_LIST is not defined.)