Conversation
|
During a port to MSVC 2019 I discovered that the explicit bool conversion works properly with the They plan to make that flag enabled by default at some point (2038?) but until then we can only wait I'm afraid (and then five more years until we can drop support for compilers that don't have it enabled by default). |
|
Recently I'm thinking about removing the implicit pointer conversion, as it causes various problems when comparing containers in
if(Containers::Optional<Containers::Array<char>> file = Utility::Path::readFile("foo.dat")) {
// the file is found, but might be empty
}
ArrayView<const char> input; // some larger string
while(!input.empty()) { // we explicitly run for as long as there's something
std::size_t bytesRead = ...;
input = input.suffix(bytesRead);
} |
The problem, in short:
In other words, currently
boolconversion is done from the data pointer, not from the size pointer. I think it should depend on the size rather than on the data, to make life easier when writing parsers and such. The following code will cycle forever, becauseinputis always some non-null pointer, even though size eventually becomes zero and one has to pay extra attention and say!input.empty()or something:That's not really intuitive, as e.g.
std::istreamalso returnsfalsewhen reaching EOF.So, fixing the bool conversion like this (as partially done in the PR already) seems like a good idea (for me at least), but there's one problem -- the bool conversion operator is disabled on MSVC as it causes ambiguities for
operator+, basically clashing with the pointer conversion operator, even though the bool conversion is explicit, due to implicit backwards compatibility with shit old C++ code (/permissive). So there are the following options:explicit operator bool()like it currently is (return _data;) and update the documentation to say it basically doesn't do what would one expect. That makes it consistent with MSVC, but practically useless and potentially dangerous if accidentally used for the wrong purpose./permissive-on everyone. Would mean dropping MSVC 2017 support, as it's known to be crashy and buggy in some cases.Add an explicit branch to the constructor which sets the data pointer toNot an option, since a lot code relies on a distinction between a null empty view and a non-null empty view.nullptrin case size is zero. That makes it consistent with Array behavior, but might break some code. (I know about at least one case in the OpenDDL parse where I'm treating zero-sized nullptr view and zero-sized non-nullptr view differently -- the first one indicating a parse error, the second indicating EOF.)Another possibility, in a different direction than this PR:
trueonly if both size is nonzero and pointer is non-null?To ensure consistency, this applies also to the
StaticArrayView, but there zero-sized views are problematic at the moment due to some non-ISO-standard zero-sized arrays being present in function signatures.Does not apply to the new
StringViewclasses, as there I deliberately don't haveconst char*conversion -- simply because not every view is null terminated and this would be a very convenient footgun.Opinions? Thank you :)