Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

“Warning: comparison is always true”

GCC (4.7.2) with -Wextra signals the following warning/error (I have -Werror enabled):

Comparison is always true due to limited range of data type [-Wtype-limits]

for the following code [try online]:

template <
    typename T,
    std::size_t N,
    bool = static_cast<std::size_t>(std::numeric_limits<T>::max()) < N>
struct validator {
    static constexpr bool validate(T value) {
        return static_cast<std::size_t>(value) < N;
    }
};

template <typename T, std::size_t N>
struct validator<T, N, true> {
    static constexpr bool validate(T) {
        return true;
    }
};

int main() {
    // Works
    static_assert(validator<int, 4>::validate(3), "Invalid");
    // Error :-(
    static_assert(validator<bool, 2>::validate(true), "Invalid");
}

I understand why the warning would occur in a normal expression context, e.g. when I would have used the following validate function:

template <typename T, std::size_t N>
bool validate(T value) {
    return static_cast<std::size_t>(value) < N;
}

– In fact, that’s why I am using the specialised template in the first place (and note that the correct template specialisation is used, and the error in my first code is raised by the template argument, not inside the function in the unspecialised template). Is there a way around this warning? If not, isn’t that a bug in the compiler?

like image 308
Konrad Rudolph Avatar asked Jan 19 '13 23:01

Konrad Rudolph


3 Answers

This has been fixed in GCC trunk, see PR 11856

So wait for approximately late April and use GCC 4.8 :-)

like image 137
Jonathan Wakely Avatar answered Oct 18 '22 08:10

Jonathan Wakely


Since I can’t wait until this is fixed (see Jonathan’s answer) I’ve selectively disabled the warning using GCC #pragma extensions:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits"
static_assert(validator<bool, 2>::validate(true), "Invalid");
#pragma GCC diagnostic pop

Note that these pragmas unfortunately need to surround the calling code even though the actual error happens in the template parameter.

like image 30
Konrad Rudolph Avatar answered Oct 18 '22 07:10

Konrad Rudolph


Here's a workaround:

template <
    typename T,
    std::size_t N,
    bool = static_cast<std::size_t>(std::numeric_limits<T>::max()) < N>
struct validator {
    static constexpr bool validate(T value) {
        return size_t_cast(value) < N;
    }
private:
    static constexpr std::size_t size_t_cast(T value) {
        return value;
    }
};

template <typename T, std::size_t N>
struct validator<T, N, true> {
    static constexpr bool validate(T) {
        return true;
    }
};

This allows the example to compile without errors in GCC 4.7.2.

like image 41
Neil Avatar answered Oct 18 '22 07:10

Neil