Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is std::string::npos == -1 always true?

The title is relatively self explanatory. I recognize the similarity to other answers, but all of those have different arrangements of operators (and therefore different casting rules). So I require an answer that clarifies this particular case.

If someone could point out the section of the standard that explains this, I will gladly vote up and accept the answer.

like image 587
randomusername Avatar asked Jun 06 '15 17:06

randomusername


People also ask

What does std::string () do?

std::string class in C++ C++ has in its definition a way to represent a sequence of characters as an object of the class. This class is called std:: string. String class stores the characters as a sequence of bytes with the functionality of allowing access to the single-byte character.

Is string the same as std::string?

There is no functionality difference between string and std::string because they're the same type.

What type is std::string?

The std::string type is the main string datatype in standard C++ since 1998, but it was not always part of C++. From C, C++ inherited the convention of using null-terminated strings that are handled by a pointer to their first element, and a library of functions that manipulate such strings.

Are C++ strings null terminated?

Actually, as of C++11 std::string is guaranteed to be null terminated. Specifically, s[s. size()] will always be '\0' .


1 Answers

NO, it is not always true. It is however a bit more complicated than it seems at first glance:

In the beginning, let us see what std::string is (21.3/1):

The header <string> defines the basic_string class template for manipulating varying-length sequences of char-like objects and four typedefs, string, u16string, u32string, and wstring, that name the specializations basic_string<char>, basic_string<char16_t>, basic_string<char32_t>, and basic_string<wchar_t>, respectively.

Start out with 21.4/5:

template<class charT, class traits = char_traits<charT>,
    class Allocator = allocator<charT> >
class basic_string {
    typedef typename allocator_traits<Allocator>::size_type size_type;
    static const size_type npos = -1;
// [other members omitted]
};

Note that while npos is initialized with -1, its type depends on Allocator::size_type, which means that without further knowledge, we cannot simply assume that string::npos == -1 will even compile.

Now, as string uses the default allocator (the template parameter has the default value in the typedef provided by the standard library after all), let us check 20.6.9:

typedef size_t size_type;

Now, we can essentially rewrite the question as: size_t(-1) == -1. What happens now depends on the types of the subexpressions: The left hand side obviously has type size_t, while the right hand side is an integer literal, which has type int, when written like this (without further qualifiers).

The result is true if size_t is at least as large as int (for standards fanatics: Has a larger or equal integer conversion rank as defined in 4.13). Otherwise, the left hand side will get promoted to int, causing a comparision like 0xFFFF == -1 (for size_t being uint16_t and int having 32 bit), which is false.

Note that while 16 bit systems themselves are not very common anymore (except for some remnants in very small form factors), int is not restricted to 32 bit by the standard. A compiler targetting x86_64 with 64 bit size_t and 128 bit int would be technically compliant.

All quotes are from the C++11 standard (ISO/IEC 14882:2011).

like image 189
gha.st Avatar answered Nov 15 '22 00:11

gha.st