   lost again with templates...
  Following up with my fixed-point template math class post from yesterday, I have expanded the operator= function to accept implicit conversions.So far it's working fine, however I've realized I also need a way to allow assignment of a fixed-point number with a different set of template parameters.template <typename T, uint fracBits>class newfxp{public:Tval;public:newfxp<T, fracBits> &operator =(int x);newfxp<T, fracBits> &operator =(double x);newfxp<T, fracBits> &operator =(const newfxp<T, fracBits> &x);template <typename _T, uint _fracBits>newfxp<T, fracBits> &operator =(const newfxp<_T, _fracBits> &x);};template <typename T, uint fracBits>template <typename _T, uint _fracBits>newfxp<T, fracBits> &newfxp<T, fracBits>::operator =(const newfxp<_T, _fracBits> &x){if (fracBits > _fracBits)val = x.val << (fracBits - _fracBits);elseval = x.val >> (_fracBits - fracBits);return *this;}The code above actually compiles and works just fine, but it generates an ugly warning on either one of the two lines that the shift amount is negative, depending on the actual value of fracBits that I'm using.Is there any way to eliminate this warning?  Or better yet, is there some way I can split this function into two different functions based on the value of the instanciated fracBits in both the source and destination classes, so I don't have to do the if() myself?Any suggestions are welcome.   
  The if statement isn't actually a big deal because, due to the nature of template instantiation and modern compilers, the if should actually be evaluated at compile-time, with the dead branch removed, hence there will be no performance penalty at run-time.This, of course, is provided that the statement inside the if is constant, but I see no reason why it shouldn't be. Turn on assembly file generation and look at the code for yourself to confirm. If the dead branches are eliminated, the compiler shouldn't complain. If it still does, you can use your compiler's directives to suppress the warning where you know it's safe and restore it immediately afterwards.I have some code which does similar work converting between arbitrary, externally-defined color formats using traits classes and which relies on the compiler to evaluate conditionals at compile-time to speed things up.   ;  I'm not really concerned about the if() itself as much as I'm concerned about the warnings.  As you mentioned, odds are the compiler is optimizing it out anyway.  However, the warnings are generated regardless if compiling in debug or release:1>sandbox.cpp(333) : warning C4293: '<<' : shift count negative or too big, undefined behavior1>   sandbox.cpp(363) : see reference to function template instantiation 'newfxp<T,fracBits> &newfxp<T,fracBits>::operator =<u32,16>(const newfxp<T,16> &)' being compiled1>   with1>   [1>  T=u32,1>  fracBits=81>   ]I could disable the compiler warning as an absolute last result, but was really looking for a better answer.Isn't there some magic in boost that might help out here?  :)   ;  Have you looked at the assembly output yet to determine that the dead branch is actually being removed? I don't recall getting these types of warnings and I do similar shift operations within conditionals in my code; I recall seeing them at one point, but they've gone away... I'll have to double-check and see what's up with my code.In the meantime, look at the assembly to verify, and if its not yet removing the dead branch try defining the fracbits template parameters (both the template class parameter and the template method parameter) as const and perhaps that will coax the compiler to cooperate.   ;template < typename T1, int I1 >struct fixed_point{T1 val;template < typename T2, int I2 >fixed_point & operator=(fixed_point< T2, I2 > const & rhs);};namespace{template < int I1, int I2, bool LhsGreater = (I1 > I2) >struct fixed_point_assign_helper{template < typename T1, typename T2 >void operator()(T1 & lhs, T2 const & rhs) const{lhs = rhs << (I1 - I2);}};template < int I1, int I2 >struct fixed_point_assign_helper< I1, I2, false >{template < typename T1, typename T2 >void operator()(T1 & lhs, T2 const & rhs) const{lhs = rhs >> (I2 - I1);}};}template < typename T1, int I1 >template < typename T2, int I2 >fixed_point< T1, I1 > & fixed_point< T1, I1 >::operator=(fixed_point< T2, I2 > const & rhs){fixed_point_assign_helper< I1, I2 >()(val, rhs.val);return *this;}Σnigma   ;int leftShiftUnsigned(int value, unsigned int distance) {  return value << distance;}int rightShiftUnsigned(int value, unsigned int distance) {  return value >> distance;}int leftShiftSigned(int value, int distance) {  // Shifting factored out to another function taking an unsigned int to avoid  // the warning  return (distance > 0)    ? leftShiftUnsigned(value, distance)    : rightShiftUnsigned(value, -distance);}template <typename T, uint fracBits>template <typename _T, uint _fracBits>newfxp<T, fracBits> &newfxp<T, fracBits>::operator =(const newfxp<_T, _fracBits> &x){val = leftShiftSigned(x.val, (fracBits - _fracBits));return *this;}Although that might inhibit optimization :( I really wish shifts were just defined to work that way with negative shift distances.   ;  Enigma's method worked out perfectly.Thanks for the responses, everyone!;  So, I just thought I'd pop by and clarify the differences between Enigma's and my own implimentation.First, as it turns out, I was still getting the warnings and had simply disabled them for small sections of code using #pragmas. In the end, the code was removed by the optimization pass, but this comes after the phases where error messages are spit out.Enigma's version uses a template specialized helper, the correct version of which is chosen during compilation. As such, only the correct version of the code is ever really there, and hence, no warnings.Enigma's way is nicer, though it comes at a small implimentation premium. It avoids warnings rather than silencing them, which is well worth the cost of admission, and it doesn't use an compiler-specific directives either, so it should be cross-platform anywhere that the template specialization is supported.   