6

While creating a version of std::basic_string_view for a private project (choices made for me: C++11; no boost:: allowed; with a pinch of NIH, so no GSL either) I came to implementing std::basic_string_view::max_size() for which the standard (n4820 21.4.2.3 Capacity) simply says:

Returns: The largest possible number of char-like objects that can be referred to by a basic_string_view.

Logically, this would be the maximum number that std::basic_string_view::size_type can represent: std::numeric_limits<std::basic_string_view::size_type>::max() which comes out at 18446744073709551615 on my platform where size_type is std::size_t.

I figured that, since I want to be compatible with the standard libraries, I should ensure that I arrive at the same number as other implementations. This is where I get lost.

Given that I have a auto max_size = string_view{"foo"}.max_size() then I get the following results:

+--------------+--------------------------+
| Library      | Result                   |
+--------------+--------------------------+
| libstdc++    | 4611686018427387899      |
| libc++       | 18446744073709551615     |
| boost 1.72.0 | 3                        |
+--------------+--------------------------+

If my interpretation is correct, then that means that libc++ and I agree on what the value should be. I feel that boost is completely wrong, since the specification for max_size is to return the largest possible number that a, not this, string_view can refer to. However, as noted in the comments, boost::string_view predates the standard and it is thus unfair to call it "completely wrong". Further, looking at the implementations of all three libraries libc++ returns

numeric_limits<size_type>::max();

libstdc++ returns

(npos - sizeof(size_type) - sizeof(void*)) / sizeof(value_type) / 4;

and boost returns:

len_;

Basically, two implementations appear to be wrong, but the question is: which one is correct?

David Brown
  • 522
  • 2
  • 12
  • n4659 is the closest document to the current standard – M.M Feb 23 '20 at 10:14
  • 3
    The boost implementation most likely predates the standard. Calling it "wrong" for not following a standard that didn't exist is a bit strong. – Mat Feb 23 '20 at 10:17
  • 2
    I have some recollection that gcc limits the maximum size of an object for practical reasons, you will probably find that it is impossible to create an object of that size (4 exabytes!). One reason to at least limit size to 2^63-1 is so that subtracting two pointers into the object doesn't cause undefined behaviour by exceeding `ptrdiff_t` limits. Perhaps you could check libstdc++ source code and see if there are relevant code comments – M.M Feb 23 '20 at 10:18
  • @M.M indeed, trying to do `new char[-1ul];` on a 32-bit system results in `error: size ‘4294967295’ of array exceeds maximum object size ‘2147483647’`. – Ruslan Feb 23 '20 at 10:24
  • @Mat, that is a fair point. – David Brown Feb 23 '20 at 11:10
  • I always viewed the definition `max_size` as unimplementable ... The exact "largest possible number" depends on many things and is often impossible to query. So I'd say the return values of GCC and Clang are both reasonable. (3, on the other hand, is unacceptable if a std implementation does it) – L. F. Feb 23 '20 at 12:37
  • I have come to the conclusion that this may be a case where `implementation defined` is probably needed. Especially when you take the `ptrdiff_t` comment in to consideration. Given that it seems to be a helper, would it not be preferable to have `max_size` defined as `static constexpr size_t max_size() noexpect`? Such that one can query the max size of a `string_view` without needing an instance. I can understand, given this, why Boost might have decided on their implementation; I wouldn't want to guess a reasonable limit for all platforms either. I might follow suit in my implementation. – David Brown Feb 23 '20 at 12:56
  • 1
    If it's intended to be compile-time constant, then why is it a non-static member function? [This might be useful](https://stackoverflow.com/questions/13137766/why-isnt-stdstringmax-size-a-compile-time-constant/13139088#13139088). – n. m. could be an AI Feb 23 '20 at 13:41
  • Interesting that you have the C++11 tag, since `std::string_view` was only introduced in **C++17**. – Adrian Mole Feb 23 '20 at 14:01
  • @n. pronouns' m. That was very interesting. In fact, that might be worthy of an answer one could accept? – David Brown Feb 23 '20 at 14:14
  • 1
    If that's an answer, then the question is a dupe... – n. m. could be an AI Feb 23 '20 at 14:17
  • I asked what max_size of a string_view is in an attempt to find out what the value is supposed to represent. According to that answer it's just some value that doesn't really matter. If you consider that a duplicate, then fair enough :) – David Brown Feb 23 '20 at 15:39
  • @Adrian Mole yes `string_view` is a C++17 feature, but it is a library feature that needs nothing of the newer language features. Thus implementable in C++11 if you extend the constructors to work with `std::string`. – David Brown Feb 23 '20 at 15:44

0 Answers0