0
votes

The ingredients:

  1. A matrix-class templated on the matrix-element-type, intended to work with sub-matrices as well as double/float etc.

  2. A matrix-member-method that returns the "true" diagonal, i.e. in case of NxN sub-matrices the diagonals of those, i.e. a vector of vectors of size N.

  3. As few restrictions as possible regarding the implementation of the sub-matrices, and no unnecessary "side-effects"/requirements when not using sub-matrices but, say, just double.

  4. Seamless usage of the matrix-class in some algorithm, e.g. conjugate gradient, which ideally should just be templated on some generic matrix- and vector-type.

The idea was to provide a functor to the GetDiagonalElements()-method of the matrix, which has a default value that just copies the diagional-element. Ignoring the actual size of the matrix (just 1x1), the following is my attempt to provide that functionality:

#include <vector>

template< typename T >
struct Matrix
{
  std::vector<T> data;
  Matrix() : data(1) {}

  // Default-functor for T2=T or convertible.
  template< typename T2 >
  struct GetDiagonalElementsFunc
  {
    void operator()( const T &t1, T2 &t2 ) { t2 = (T2)t1; }
  };

  template< typename T2, typename GetDiagonalElementsFunctor >
  void GetDiagonalElements( std::vector<T2> &diag,
    GetDiagonalElementsFunctor gdeFunctor=GetDiagonalElementsFunc<T2> 
  {
      diag.resize(1)
      gdeFunctor( data[0], diag[0] );
  }
};

void foo()
{
  Matrix<double> mat;
  std::vector<double> diag;
  mat.GetDiagonalElements(diag);

}

The compiler "says": could not deduce template argument for 'GetDiagonalElementsFunctor'

Guess the functor as template-argument is not needed - I tried but didn't get that to work either, probably simple (?), though any help appreciated, kind regards, Derik.

PS: Ideally, if possible, no extra/intermediate helper-types. No Boost, no C++11.

Additional question: What if I'd want to do the same but specify the diagonal-access-functor as part of the matrix-template-declaration (?), how ?

1

1 Answers

3
votes

You cannot use default template parameters in functions in C++98... So, you should use struct, or two functions for this case... Example with two functions

  template< typename T2, typename Functor>
  void GetDiagonalElements( std::vector<T2> &diag, Functor gdeFunctor)
  {
      diag.resize(1);
      gdeFunctor( data[0], diag[0] );
  }

  template<typename T2>
  void GetDiagonalElements( std::vector<T2>& diag)
  {
     GetDiagonalElements(diag, GetDiagonalElementsFunc<T2>());
  }