模板类成员函数的C ++部分专业化

Rai*_*Rai 5 c++ templates partial-specialization

确实确实存在一些密切相关的问题,但是我正在努力找出如何应用其解决方案。

我有一个traits类,如下所示,用于处理我正在使用的boost::numeric:ublas::matrix矩阵(以及其他矩阵实现)。我只想对switch_storage_order注释中所示的进行部分专业化,但是由于函数无法部分进行专业化,因此这失败了。

我不想部分专门化该matrix_traits结构,因为这会带来重新定义其所有成员的开销。一种解决方案是将每个与矩阵相关的函数分成各自的结构,但最好将它们分组在一个特征类中。

有任何想法吗?也可以随意评论特质概念的一般应用。

#include <boost/numeric/ublas/matrix.hpp>

enum matrix_storage_order {row_major, column_major};

template<class matrix_type>
struct matrix_traits {
  // Default expects c-style row_major storage order.
  static matrix_storage_order get_storage_order(const matrix_type& m)
  { return row_major; }

  // By default can't change storage order so simply transpose.
  static void switch_storage_order(matrix_type& m) { m.transpose(); }
};

namespace ublas = boost::numeric::ublas;

/* This doesn't work with error C2244:
  * 'matrix_traits<matrix_type>::switch_storage_order' : unable to match function
  * definition to an existing declaration
  */
// template<class value_type>
// void matrix_traits<ublas::matrix<value_type> >::switch_storage_order(
//     ublas::matrix<value_type>& m) {
//   m = boost::numeric::ublas::trans(m);
// }

typedef boost::numeric::ublas::matrix<double> matrix_double;

template<>
void matrix_traits<matrix_double>::switch_storage_order(matrix_double& m) {
  m = boost::numeric::ublas::trans(m);
}

template <class matrix_type>
void function_requiring_column_major_storage_order(matrix_type& m) {
  bool switch_order =
    matrix_traits<matrix_type>::get_storage_order(m) == row_major;
  if (switch_order) matrix_traits<matrix_type>::switch_storage_order(m);
  // ... Do some work on m.
  if (switch_order) matrix_traits<matrix_type>::switch_storage_order(m);
}

int main() {
  matrix_double m;
  // ... Fill the matrix.
  function_requiring_column_major_storage_order(m);
}
Run Code Online (Sandbox Code Playgroud)

Jar*_*d42 2

如果你可以改变 的实现static void switch_storage_order(matrix_type& m),你可以使用类似的东西:

// By default can't change storage order so simply transpose.
static void switch_storage_order(matrix_type& m) { transposer<matrix_type>()(m); }
Run Code Online (Sandbox Code Playgroud)

// generic case
template <typename T>
struct transposer {
    void opearator () (T& m) const { m.transpose(); }
};

// your specialization.
template<typename T>
struct transposer<ublas::matrix<T>> {
    void opearator () (ublas::matrix<T>& m) const { m = boost::numeric::ublas::trans(m); }
};
Run Code Online (Sandbox Code Playgroud)