Comparison of different types in a template

I want to create a function that will check if the parameters are out of range.

I wrote 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 a warning:

 warning: comparison between signed and unsigned integer expressions 

How can I create a function that will safely handle all types?

+5
source share
4 answers

As @Borisbn said you can do it 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); } } 

EDIT

I think you could do it 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); } 
+1
source

Instead of using the built-in 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 will still receive warnings, so you will probably also want #pragma GCC diagnostic push; ignored; pop around it #pragma GCC diagnostic push; ignored; pop #pragma GCC diagnostic push; ignored; pop #pragma GCC diagnostic push; ignored; pop .

+1
source

You need to infer what is the largest type among the three. You can 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 must support decltype , as well as this using construct.

0
source

As a combination of the o11c and Ajay answers, you can use this comparison function, which does not give 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.

Demo

0
source

Source: https://habr.com/ru/post/1204235/


All Articles