FelB FelB - 2 months ago 7
C++ Question

What is the type of string.size() in C++?

I have the following code:

#include<iostream>
#include<string>
int main()
{
std::string s = "458";
std::cout <<s.size()-4;
}


When I run this I get 42944935 or something like this. But when I run it with the following modification:

int main()
{
std::string s = "458";
int i = s.size();
std::cout << i -4;
}


I get -1, which I would have expected from the first code. Can someone explain what is happening here?

Answer

For historical reasons the return type of std::string::size() is size_t, which is an unsigned type sufficient for the largest possible array size.

You can work around that by defining a number of general size/length-functions, like

using Size = ptrdiff_t;  // signed type

template< class Collection >
constexpr auto n_items( Collection const& c )
    -> Size
{ return c.size(); }

// Raw array. Using size_t template param for g++ compatibility.
template< class Item, size_t n >
constexpr auto n_items( Item (&)[n] )
    -> Size
{ return n; }

Here I used the name n_items because C++17 will define a general size function that, unfortunately, returns size_t (and conflates a number of notions of size, also unfortunate). One doesn't want a name conflict there.


Where you don't have such functions available an alternative is to express a size as the difference of std::end and std::begin, e.g. end(s) - begin(s). The difference type for raw pointers is ptrdiff_t (which is signed), and the default difference type for iterators like you get from std::string::begin(), is also ptrdiff_t, from std::iterator_traits.