Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partial template specialization of a single method of a bigger class

Tags:

c++

templates

I have the following class;

template<int N, int M, int K>
class BaumWelch
{
  //lots of stuff
  const TransitionMatrixTemplate<N, M> randomA()
  { //.... }
}

now I would like to specialize the method randomA for N=1. How can I do it?

I tried following this question: Template specialization of a single method from a templated class, but it doesn't seem to work with partial specialization. This question: C++ partial method specialization seems more relevant, but it suggest specializing the whole class (which is quite big in my case). Is it possible to specialize the whole class, but actually specialize only this one method?

like image 214
Grzenio Avatar asked Jan 13 '23 13:01

Grzenio


2 Answers

I would like to specialize the method randomA for N=1. How can I do it?

You've discovered that partial specialization for functions is not allowed.

However, you can fully specialize a "detail" implementation of the code.

  template<int TheN>
  detail_randomA();

  const TransitionMatrixTemplate<N, M> randomA()
  {
      return detail_randomA<N>();
  }

And outside the class declaration:

  template<int N, int M, int K>
  template<int TheN>
  BaumWelch<N,M,K>::detail_randomA()
  {
      //lots of stuff when N != 1
  }

  template<int N, int M, int K>
  template<>
  BaumWelch<N,M,K>::detail_randomA<1>()
  {
      //lots of stuff when N == 1
  }
like image 50
Drew Dormann Avatar answered Jan 31 '23 02:01

Drew Dormann


You can't partially specialize function templates, but you can pass the work off to class templates. Here's a fully working example:

#include<iostream>
using namespace std;

// This first template isn't important, it's just the return value from your function
template <int N, int M>
struct TransitionMatrixTemplate {
        void print_me() const {
                cout << N << ',' << M << endl;
        }
};

// We need to announce the existence of the BaumWelch class template early here,
// in order that it can appear in the signature of our impl_randomA class.
template<int N, int M, int K>
struct BaumWelch;

// Now, the first important bit of code.  The default implementation
template<int N, int M, int K>
struct impl_randomA {
        static TransitionMatrixTemplate<N,M> f(BaumWelch<N,M,K> * This) {
                return TransitionMatrixTemplate<N,M>();
        }
};

// Next, is the partially specialized version.
template<int M, int K>
struct impl_randomA<1,M,K> {
        static TransitionMatrixTemplate<1,M> f(BaumWelch<1,M,K> * This) {
                cout << "<Special for N=1> ";
                return TransitionMatrixTemplate<1,M>();
        }
};

// Finally, The BaumWelch class and its call out to impl_randomA.
template<int N, int M, int K>
struct BaumWelch {
        const TransitionMatrixTemplate<N, M> randomA() {
                return impl_randomA<N,M,K> :: f(this);
        }
};

int main() {
        BaumWelch<2,3,4>() . randomA() . print_me();
        BaumWelch<1,3,4>() . randomA() . print_me();
}
like image 36
Aaron McDaid Avatar answered Jan 31 '23 01:01

Aaron McDaid