Reputation: 1501
I want to create a function which will check if parameters are out of range.
I have written this:
template<typename X,typename Y,typename Z >
void checkParameter( X val, Y lower, Z upper)
{
if( ( val > upper) || ( val < lower) )
{
log("checkParameter, val = % , lower= % , upper= % \n", val,
lower,upper );
ASSERT(false);
}
}
However, when I do this
uint32_t var = 5000;
checkParameter( var, 0, 262143);
I get the warning:
warning: comparison between signed and unsigned integer expressions
How can I make a function which safely will handle all types?
Upvotes: 5
Views: 584
Reputation: 41301
As a combination of o11c's and Ajay's answers, you can use this comparison function which doesn't produce any warnings:
template<typename A, typename B>
bool lt(A a, B b) {
if (a < 0 && b >= 0)
return true;
if (a >= 0 && b < 0)
return false;
using TYPE = decltype(a + b);
return static_cast<TYPE>(a) < static_cast<TYPE>(b);
}
It works with any combination of signed and unsigned numeric types.
Upvotes: 1
Reputation: 686
As @Borisbn said you could do this like this:
template<typename type >
void checkParameter( type val, type lower, type upper)
{
if( ( val > upper) || ( val < lower) )
{
log("checkParameter, val = % , lower= % , upper= % \n", val,
lower,upper );
ASSERT(false);
}
}
I think you could do this like this:
template<bool A, bool B, bool C>
struct test {
template < typename T1, typename T2, typename T3>
void parameters (T1, T2, T3) { /* Mismatching types */ }
};
template<>
struct test<true, true, true> { // all parameters will be signed
template < typename T1, typename T2, typename T3>
void parameters (T1 a, T2 b, T3 c) {
/* do your test here */
}
};
template<>
struct test<false, false, false> { //all parameters will be unsigned
template < typename T1, typename T2, typename T3>
void parameters (T1 a, T2 b, T3 c) {
/* do your test here */
}
};
template < typename T1, typename T2, typename T3>
void testParameters(T1 a, T2 b, T3 c) {
test<std::is_signed<T1>::value, std::is_signed<T2>::value, std::is_signed<T3>::value>::parameters(a,b,c);
}
Upvotes: 1
Reputation: 16016
Instead of using builtin operator <
, use a function that returns the correct result in case of sign mismatches
template<class A, class B>
bool lt(A a, B b)
{
if (a < 0 && b >= 0)
return true;
if (a >= 0 && b < 0)
return false;
return a < b;
}
You'll still get warnings, so you'll probably also want some #pragma GCC diagnostic push; ignored; pop
around it.
Upvotes: 1
Reputation: 18411
You need to deduce what is the biggest types amongst three. You may use this approach:
template<typename X, typename Y, typename Z >
void checkParameter(X val, Y lower, Z upper)
{
using TYPE = decltype(val + lower + upper);
if (((TYPE) val > (TYPE) upper) || ((TYPE) val < (TYPE)lower))
{
ASSERT(false);
}
}
Your compiler should be supporting decltype
as well as this using
construct.
Upvotes: 0