4

由于以下代码中的函数模板是类模板的成员,因此如果不专门化封闭类就无法专门化它。

但是,如果编译器的全部优化已启用(假设 Visual Studio 2010),以下代码中的 if-else-statement 会得到优化吗?如果确实如此,这是否意味着出于所有实际目的,这是一个没有任何性能成本的函数模板专业化?

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

很有可能它会被优化。但是,如果您想确保可以if通过使用模板来使用编译时,例如 Boost 的 MPLif_实现。

或者你可以使用 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

谢谢。因为我想确定条件被优化了(因为它需要经常在循环内部深处调用,并且我在循环外部使用 switch-case 来选择正确的路径),我可能最终会使用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;}
};

对我来说,这似乎没有约翰内斯的建议那么混乱。尽管最后一个(默认)情况可能会变得非常难看。

于 2010-04-11T13:41:57.553 回答