开发者

Does this mimic perfectly a function template specialization?

Since the function template in the following code is a member of a class template, it can't be specialized without specializing the enclosing class.

But if the compiler's full optimi开发者_运维知识库zations are on (assume Visual Studio 2010), will the if-else-statement in the following code get optimized out? And if it does, wouldn't it mean that for all practical purposes this IS a function template specialization without any performance cost?

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


Chances are it will be optimized. But if you want to be sure you can use a compile-time if by using templates, e.g. Boost’s MPL if_ implementation.

Or you can use SFINAE (Boost.enable_if).


Usually the way to solve this kind of problem is through overloading

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

This mimics explicit specializations quite well, and even works in cases where type check for the other paths would go mad (unlike the if solution)

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

That works because this path is only taken if I != 0. Now in your case, i first of all wonder why you don't just pass a normal function argument. You don't seem to need the compile time nature of 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;
}

This also has good chances of being optimized if the compiler inlines the function call. Using the template non-type parameter where it's not strictly necessary only limits the abilities of that function not to work with runtime values.


Thanks. Since I want to be certain the conditional is optimized out (because it needs to called very often deep inside loops and I use a switch-case outside the loops to pick the correct path), I'll probably end up using enable_if_c something like in the following code:

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

To me this seems a bit less cluttered than the suggestion by Johannes. Although the last (default) case can get quite ugly.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜