4

I have found some templated code which at some point performs the following check:

template<class IntegralType>
void randomFunction(IntegralType t)
{
    ...
    if (t < 0)
    ...
}

The idea of the code is that t is of an integral type (either signed or unsigned). The code works just fine regardless of signedness, but the compiler issues a warning because in the case of an unsigned integer the check will always be true.

Is there a way in C++03 of modifying the code to get rid of the warning without suppressing it? I was thinking of checking the signedness of T somehow, don't know it it's possible.

I am aware of C++11's is_signed but I am not sure how it could be implemented in C++03.

user2891462
  • 3,033
  • 2
  • 32
  • 60
  • You could always use *specialization* for an `unsigned IntegralType`, which doesn't do the comparison and calls one or more functions for the otherwise common code. – Some programmer dude Dec 18 '17 at 13:56
  • @Someprogrammerdude How would that look? `template void randomFunction(unsigned IntegralType)` interprets `unsigned` as `unsigned int` and complains. – user2891462 Dec 18 '17 at 14:27
  • Possible duplicate of [Comparison is always false due to limited range ... with templates](https://stackoverflow.com/questions/2056996/comparison-is-always-false-due-to-limited-range-with-templates) – jww Jan 02 '18 at 15:55

3 Answers3

6

With Tag dispatching and traits:

template <typename T>
bool is_negative(T t, std::true_type)
{
    return t < 0;
}
template <typename T>
bool is_negative(T t, std::false_type)
{
    return false;
}

template<class IntegralType>
void randomFunction(IntegralType t)
{
    ...
    if (is_negative(t, std::is_signed<IntegralType>::type())
    ...
}

std::is_signed can be implemented in C++03.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
3

C++11 has is_signed and cppreference shows this as possible implementation:

namespace detail {
template<typename T,bool = std::is_arithmetic<T>::value>
struct is_signed : std::integral_constant<bool, T(-1) < T(0)> {};

template<typename T>
struct is_signed<T,false> : std::false_type {};
} // namespace detail

template<typename T>
struct is_signed : detail::is_signed<T>::type {};

The problem is that is_integral_constant is only available in C++11 too, however, this might a starting point for you to implement the same in C++03.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • `integral_constant` is almost trivial to backport to C++03 anyway, as it is a purely library solution. Code from an early C++11 compiler's include files for `integral_constant` and all the basic type traits should compile as-is in C++03. – Luis Machuca Dec 18 '17 at 13:49
  • Does anyone know if this works on OSX, like versions 10.8 and 10.9? Apple provides an unusual C++ std library at times. – jww Jan 02 '18 at 16:41
1

I've been looking for a solution for this problem for some time.

The best solution I've found was using the same idea as in this answer:

    if (!(t == 0 || t > 0))

which it may be a compiler-specific workaround but at least in g++ 4.4.7 the warning fades away.

miravalls
  • 365
  • 1
  • 7