Awesome talk. However, is emplace_back of the vector into itself guaranteed to work? I think it might only be working because of an implementation which doesn't increment its internal size until after construction, rather than incrementing and rolling back if an exception is thrown (which I don't believe is forbidden by the standard).
Similarly, an emplace into the middle of the vector with itself seems like it could never work.
I can see how push_back/insert would work, because the copies would be made at the call site, before the vector is modified.
Just seems a little dangerous, unless I'm missing something.
Oddly enough, today I just added the first do-while loop into our year-old codebase. It's not something I like to do often, but it's occasionally useful. It was the do-while-false idiom which some people may not be aware of:
The idea is to introduce a non-looping block from which you can break in order to perform simple 'local exception handling' when errors occur. In my case, I was reading a nested JSON object returned from Facebook and if any part of it wasn't in the format I expected, I wanted to ignore it:
auto& picture = json["picture"];
auto& pictureData = picture["data"];
auto& pictureUrl = pictureData["url"];
// Do something with pictureUrl.GetString() here
} while (false);
The alternatives would be:
Actual exceptions - overkill, much uglier, slower and not an option in my exceptions-disabled codebase.
Invert the conditions and have increasingly-indented code - ugly and doesn't scale.
goto the end of the block - not terrible, but goto is not politically-correct. Also, I think the block makes the intended scope of the feature clearer.
Introducing a function which you can return from early - probably not too bad in this case, but often you need to pass a lot of the context from the original function to make it work. Also, the function has no real meaning in and of itself - it is only being used to avoid a goto or do-while-break construct.
do-while-false also has benefits in multi-statement macros:
Thanks for replying and I understand all of your points. Let me just clarify that when I said 'worse than NULL', I meant bigger and uglier in the code, e.g. MYLIBRARY_NULLPTR or something, as opposed to the semantics which are obviously much better.
However, in general, a C++ library author (such as myself) cannot know in advance whether or not his library will be used in a C++/CLI build or not and, to prevent this being a problem, needs to avoid anything that will cause portability issues. In this
case, avoiding nullptr in favour of 'good old 0'. Obviously this would only be where the semantics don't matter; fortunately, in a template library, you tend to only need to care about the types coming in, rather than the ones you use in the implementation.
But it would've been nice as a self-documentation feature.
Template libraries already have to deal with different compilers (and versions of each compiler) for different reasons; it would've been nice if this otherwise-great new feature didn't have to be avoided or made a special case.
Regarding the problems with nullptr and C++/CLI. Does this mean that a third-party template library that uses nullptr (rather than __nullptr) in its headers will be unable to be included in any C++/CLI project?
This is a perfectly feasible situation even in interop code, where you have a C++/CLI type wrapping a C++ type which contains a member from this template library.
This would seem to leave the template library little choice but to define a macro to map to either nullptr or __nullptr depending on whether it's a C++/CLI build or not (which it shouldn't care about, since it's a pure C++0x library), which ends up being
worse than the NULL macro!