Search code examples
c++eigen3

class using templated eigen matrix


I wrote a class like

class abc
{
public:
    template <typename Derived >
    abc( const Eigen::MatrixBase < Derived > &matA,
         const Eigen::MatrixBase < Derived > &matB,
         Eigen::MatrixBase < Derived > &matC );
};

template <typename Derived >
abc::abc( const Eigen::MatrixBase < Derived > &matA,
          const Eigen::MatrixBase < Derived > &matB,
          Eigen::MatrixBase < Derived > &matC )
{
    matC.derived().resize( matA.rows(), matA.cols() );

    for( int r = 0; r < matA.rows(); r++ )
    {
        for( int c = 0; c < matA.cols(); c++ )
        {
            matC(r,c) = log( matA(r,c) )/log( matB(r,c) );
        }
    }
}

but when using class abc in main i get undefined reference error

typedef Eigen::Matrix< float, Eigen::Dynamic, Eigen::Dynamic > Matrix_Float;
main()
{
Matrix_Float matA, matB, matC;
// put values in matA, matB
    abc cls_abc( matA, matB, matC );
}

error is error: undefined reference to `abc::abc < Eigen::Matrix < float, -1, -1, 0, -1, -1> > (Eigen::MatrixBase < Eigen::Matrix < float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase < Eigen::Matrix < float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase < Eigen::Matrix < float, -1, -1, 0, -1, -1> > &)'

is there anything wrong with syntax of class definition?

help please.


Solution

  • You have a few issues. First, with template classes, you need to have the implementation available with the declaration (i.e. in the .h file, not the .cpp). Second, you want the class to be templated, note the constructor. Third, when using a templated class, you need to specify the template parameter.

    Putting all that together, your class (.h) file should look like this:

    template <typename Derived > class abc  // Template the class
    {
    public:
        //template <class Derived > // Don't put this here, but above
        abc(
            const Eigen::MatrixBase < Derived > &matA,
            const Eigen::MatrixBase < Derived > &matB,
            Eigen::MatrixBase < Derived > &matC);
    };
    
    template <typename Derived >
    abc<Derived>::abc(
        const Eigen::MatrixBase < Derived > &matA,
        const Eigen::MatrixBase < Derived > &matB,
        Eigen::MatrixBase < Derived > &matC)
    {
        matC.derived().resize(matA.rows(), matA.cols());
    
        for (int r = 0; r < matA.rows(); r++)
        {
            for (int c = 0; c < matA.cols(); c++)
            {
                matC(r, c) = log(matA(r, c)) / log(matB(r, c));
            }
        }
    }
    

    and your main() should look like:

    int main(int argc, char* argv[]) // just "main()" is so passé
    {
        Matrix_Float matA, matB, matC;
        // put values in matA, matB
        abc<Matrix_Float> cls_abc(matA, matB, matC);
    }