I have not thought about it much, but perhaps you can use something from the boost library.

http://www.boost.org/doc/libs/1_40_0...its_class.html

Code:
template <typename T1, typename T2>
inline complex<typename boost::numeric::conversion_traits<T1,T2>::supertype> operator + (const complex<T1> & a, const complex<T2> & b)
{
   return complex<typename boost::numeric::conversion_traits<T1,T2>::supertype>(a.real() + b.real(), a.imaginary() + b.imaginary());
}
The problem with this is you seem to want to always promote signed unsigned combinations to unsigned.