On 8/11/2013 12:40, Quoth Rob Stewart:
On Nov 7, 2013, at 5:00 PM, Gavin Lambert
wrote: const char s[] = {'0', '1', '2'}; /* User knows that this is not zero terminated*/ string_ref test(s); // Size of array is determinated at this point. Why not have {ptr, 3}? [...] The first example in particular actually seems potentially dangerous to me, because the ability to handle the non-terminated string is "hidden", making it more likely that the author would forget and pass sto something else that's expecting a terminated string.
If code assumes a string_ref refers to a null-terminated string, that code is wrong.
I was referring to "s", the original char array, not to "test", the string_ref. ie. if string_ref handled it gracefully and "hidden", the user might forget that other things they can legally (according to the compiler) pass "s" to might not. But that's reaching a bit. My main objection relates to the surprise decay from array to pointer if the code is refactored, and that this would change the behaviour in a potentially surprising way if that constructor existed, without a sufficiently obvious change to the code.
Why not add named constructors to clarify the caller's intent?
That would be better. Still, where an lvalue is available, I don't see any particular benefit to this -- almost anything you could do with this suggested new constructor you could do with string_ref(s, boost::size(s)). (Or _countof, or ARRAY_LENGTH, or sizeof, depending on your char type and platform of choice.) The only case I can see that it might provide some benefit (other than being slightly shorter) would be when passing a string literal directly -- but string literals are always null-terminated, and the compiler should be able to optimise away the strlen, so I don't think it gains much in the end. I suppose it's possible to imagine other cases where you might have an rvalue array, but most that I can think of seem overly contrived to me, especially as the utility of string_ref on an rvalue is limited since it's a non-owning object.