部分模板专门化更大类的单个方法

时间:2013-04-23 15:59:55

标签: c++ templates

我有以下课程;

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

现在我想将方法​​randomA专门用于N = 1。我该怎么办?

我尝试过这个问题:Template specialization of a single method from a templated class,但它似乎不适用于部分专业化。这个问题:C++ partial method specialization似乎更相关,但它建议专门研究整个班级(在我的案例中这是非常大的)。是否可以专门化整个班级,但实际上只专注于这一种方法?

3 个答案:

答案 0 :(得分:6)

  

我想将方法​​randomA专门用于N = 1。我该怎么办?

您已发现不允许对函数进行部分特化。

但是,您可以完全专门化代码的“详细”实现。

  template<int TheN>
  detail_randomA();

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

在课堂宣言之外:

  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
  }

答案 1 :(得分:2)

您不能部分专门化功能模板,但您可以将工作传递给模板。这是一个完全有效的例子:

#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();
}

答案 2 :(得分:1)

简短的回答是“你没有”。

让您轻松完成自己想做的事情(让randomAN=1采取不同的行为)的方法是将const TransitionMatrixTemplate<N, M> randomA()填充到CRTP父级中,然后部分专门化N=1

template<typename D, int N, int M, int K>
struct Bob_Base {
  static_assert( std::is_base_of< D, Bob_Base<D, N, M, K> >::value, "D must be derived from Bob_Base" );
  D* self() { return static_cast<D*>(this);
  D const* self() const { return static_cast<D*>(this);
  const TransitionMatrixTemplate<N, M> randomA()
  {
    // use self()-> instead of this-> in here to access Bob methods and date
  }
};
template<typename D,int M, int K>
struct Bob_Base< D, 1, M, K > {
  static_assert( std::is_base_of< D, Bob_Base<D, N, M, K> >::value, "D must be derived from Bob_Base" );
  D* self() { return static_cast<D*>(this);
  D const* self() const { return static_cast<D*>(this);
  const TransitionMatrixTemplate<1, M> randomA()
  { /* N=1 version  */ }
};

template<int N, int M, int K>
struct Bob : Bob_Base<Bob<N, M, K>, N, M, K>
{
  //lots of stuff, but no TransitionMatrixTemplate
}

这只是重要的如果 N==1无法编译的代码(反之亦然)。