Search code examples
c++comparisonwarningsunsigned-integersize-t

Comparison size_t variable with -1 (maximum size value) in c++ code


I'm refactoring a library and trying to get rid of many gcc warnings. The big part of these warning are about signed / unsigned comparison and are related to the usage of size_t. The library works on 64 bit Linux systems.

A programmer used -1 as the special value similar to std::string::npos. There are many places in the library where code looks like this:

class AnnotationBase
{
    public:
        size_t m_offset = -1;
        size_t m_length = -1;

}

...

AnnotationBase foo(const std::string& text, const AnnotationBase& annot)
{
    AnnotationBase newAnnot;

    // do some job with annotations and text
    ...

    if(newAnnot.m_offset == -1)
    {
        // do some other job
        ...
    }

    return newAnnot;
}

The problem lies in the warning that gcc generates on the line if(newAnnot.m_offset == -1) because of a signed / unsigned comparison:

"warning: comparison between signed and unsigned integer expressions [-Wsign-compare]"

What is the proper way to compare size_t variable in C++ with the maximum value (-1) without warning? Doing this like if(newAnnot.m_offset == std::numeric_limits<size_t>::max()) is very inconvenient due to complexity and length of this expression.

Is it a good way to use C-style defined value SIZE_MAX or it is better to create own constant like namesapce libling { const NONE = std::numeric_limits<size_t>::max(); } (Creating new constant leads to many similar constants in different libraries and namespaces like libling::NONE, libother::UNKNOWN, liblongnamesapcename::NOTHING)?


Solution

  • You could do what std::string does and define a static const size_t AnnotationBase::npos = -1. Then use that in comparisons as a convention. I wouldn't consider one constant per library a problem, but if you want to avoid that, you can use std::string::npos directly (that makes the code more rigid though).