C++テンプレートでerror: no match for ‘operator+’がでる


以下のテンプレートの関数を、

[code]

    complex<double> c = u16todbm<complex<double> >(10, 32768.0, 0.0);
    
[/code]

と呼ぶと問題なくコンパイルできますが、

[code]

    complex<short> c = u16todbm<complex<short> >(10, 32768.0, 0.0);
    
[/code]

に変更すると、`*`や`+`を使用している行で、

> error: no match for ‘operator*’  
>  error: no match for ‘operator+’

が発生してコンパイルが出来ません。

・呼ばれる側

[code]

    template<typename samp_type>
    samp_type u16todbm(samp_type a, double add, double mul)
    {
      // scale offset
      a = a * mul;
      a = a + add;
    
      return a;
    }
    
[/code]

・呼ぶ側

[code]

    int main(int argc, char* args[])
    {
      complex<short> c = u16todbm<complex<short> >(10, 32768.0, 0.0); // コンパイルエラー
      complex<double> c = u16todbm<complex<double> >(10, 32768.0, 0.0); // コンパイル通る
    }
    
[/code]

complexとdoubleの*や+が定義されていないのか？と思いますが、実装方法がわかりません。  
お教え願えないでしょうか。



[code]

    int a = 1.0;
    
[/code]

とはかけない言語仕様(浮動小数点数を整数へ変換する際に切り捨てや丸めなどいくつかの方法があるため一意に変換することができず暗黙変換が定義されない)なのでcomplex<T>でTが整数型の場合は四則演算可能な型はTへの暗黙変換可能な型に対してしか定義されていない(定義すべきでないから)と思います。complexの定義を見ていないので推測ですが厳密にはTの値を実部と仮定するTからcomplex<T>への暗黙変換が定義されているように思います。  
以上からu16todbmは以下のような使い方が適切だと思います。

[code]

    u16todbm<complex<short>>(10, 32768, 0);
    
[/code]

あえて浮動小数点数を指定したいのであれば整数への変換を明示的に実装したu16todbm相当の別のテンプレート関数を定義すべきと思いますが、実装してみると若干不格好なものになりますね。

[code]

    template<typename samp_type, typename cast_type>
    samp_type u16todbm_cast(samp_type a, double add, double mul)
    {
      a = a * (cast_type)mul;
      a = a + (cast_type)add;
      return a;
    }
    
[/code]

手元にC++環境がなく確認できてませんので間違いなどあった場合はご容赦ください

