这是否完全模仿功能模板专业化?

时间:2010-04-11 11:22:32

标签: c++ templates visual-studio-2010 function specialization

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

但是如果编译器的完全优化处于启用状态(假设是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;
}

3 个答案:

答案 0 :(得分:3)

可能会优化它。但是,如果您想确定,则可以使用模板使用编译时if,例如Boost的MPL if_实施。

或者您可以使用SFINAE(Boost.enable_if)。

答案 1 :(得分: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;
}

如果编译器内联函数调用,这也很有可能被优化。使用非严格必要的模板非类型参数仅限制该函数不能使用运行时值的能力。

答案 2 :(得分:0)

感谢。因为我想确定条件被优化了(因为它需要经常调用深层内部循环并且我在循环外部使用switch-case来选择正确的路径),我可能最终会使用{{3}类似于以下代码中的内容:

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;}
};

对我来说,这似乎比约翰内斯的建议更混乱。虽然最后一个(默认)案例可能会非常难看。