4

次のコードの関数テンプレートはクラス テンプレートのメンバーであるため、外側のクラスを特殊化せずに特殊化することはできません。

しかし、コンパイラの完全な最適化がオンになっている場合 (Visual Studio 2010 を想定)、次のコードの if-else ステートメントは最適化されますか? もしそうなら、それはすべての実用的な目的のために、これはパフォーマンスコストのない関数テンプレートの特殊化であることを意味しませんか?

template<typename T>
struct Holder
{
    T   data;

    template<int Number>
    void saveReciprocalOf();
};

template<typename T>
template<int Number>
void Holder<T>::saveReciprocalOf()
{
    //Will this if-else-statement get completely optimized out
    if(Number == 0)     data = (T)0;
    else                data = (T)1 / Number;
}

//-----------------------------------
void main()
{
    Holder<float> holder;
    holder.saveReciprocalOf<2>();
    cout << holder.data << endl;
}
4

3 に答える 3

3

最適化される可能性があります。ただし、Boost の MPL実装など、テンプレートを使用してコンパイル時に使用できることを確認したい場合。ifif_

または、SFINAE ( Boost.enable_if )を使用できます。

于 2010-04-11T11:23:59.127 に答える
1

通常、この種の問題を解決する方法は、過負荷を使用することです

template<typename T>
struct Outer {
  template<int I>
  void inner() { 
    inner(int_<I>());
  }

private:
  template<int I>
  struct int_ { };

  void inner(int_<0>) {
    // for I == 0
  }

  template<int I>
  void inner(int_<I>) {
    // for others...
  }
};

これは明示的な特殊化を非常によく模倣し、他のパスの型チェックが狂った場合でも機能します (ifソリューションとは異なります) 。

// ...
  template<int I>
  void inner(int_<I>) {
    int tmp[I];
  }
// ...

このパスはI != 0. あなたの場合、まず、なぜ通常の関数引数を渡さないのか疑問に思います。のコンパイル時の性質は必要ないようですI

// works just fine too in your example
template<typename T>
void Holder<T>::saveReciprocalOf(int Number)
{
    // Will this if-else-statement get completely optimized out
    if(Number == 0)     data = (T)0;
    else                data = (T)1 / Number;
}

コンパイラが関数呼び出しをインライン化する場合、これも最適化される可能性が高くなります。厳密には必要ではないテンプレートの非型パラメーターを使用すると、その関数の機能がランタイム値で機能しないように制限されるだけです。

于 2010-04-11T11:55:37.973 に答える
0

ありがとう。条件が最適化されていることを確認したいので(ループの奥深くで頻繁に呼び出す必要があり、ループの外側でスイッチケースを使用して正しいパスを選択するため)、おそらくenable_if_cのようなものを使用することになります次のコード:

using boost::enable_if_c;

template<typename T>
struct Dummy
{    
    template<int N>
    typename enable_if_c<N==2,bool>::type             isPrimary() {return true;}

    template<int N>
    typename enable_if_c<N==3,bool>::type             isPrimary() {return true;}

    template<int N>
    typename enable_if_c<N==5,bool>::type             isPrimary() {return true;}

    template<int N>
    typename enable_if_c<N!=2&&N!=3&&N!=5,bool>::type isPrimary() {return false;}
};

私には、これは Johannes の提案よりも少しすっきりしているように思えます。最後の(デフォルト)ケースはかなり醜いものになる可能性がありますが。

于 2010-04-11T13:41:57.553 に答える