Template member function help.

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jason

    #1

    Template member function help.

    /*
    I have never use template before, so bear with me.

    Here is what I am trying to do:

    I declare an abstract base class MatrixInterface with template to
    define an interface for all my subsequent Matrix class. In
    MatrixInterface class, I overloaded the << operator by calling a pure
    virtual function PrintDebugMessa ge(ostream &os); then I can implement
    the function on individual Matrix classes later.

    I create a Matrix class called SimpleMatrix, and implemented
    PrintDebugMessa ge(). Everthing works great until I want to implement
    different behavior depending whether it's

    template<typena me DataTypevoid
    SimpleMatrix<Da taType>::PrintD ebugMessage(... ); //this is fine

    or

    //error
    template<typena me DataTypevoid SimpleMatrix< SimpleMatrix<Da taType>
    >::PrintDebugMe ssage(...);
    I want to print out data differently if a instance of my SimpleMatrix
    is a collection of sub-matrices of type SimpleMatrix. However, I can't
    get that to work.

    If I sepcialize the template parameter like:

    // works, but now only when submatrices has type of SimpleMatrix<in t>
    template<void SimpleMatrix< SimpleMatrix<in t>
    >::PrintDebugMe ssage(...);
    then it works. How I generalize the function above to handle
    SimpleMatrice submatrix of all type?


    Below is a sample code of my problem. It compiles on gcc 3.2.3 and
    intel c++ 8.1
    */
    /*************** *************** **************

    *************** *************** **************/
    #include <iostream>
    #include <typeinfo>

    using namespace std;

    /*************** *************** ******
    ** ABC for all Matrix class
    *************** *************** *******/
    template<typena me DataType>
    class MatrixInterface
    {
    public:
    template<typena me T>
    friend ostream & operator<<(ostr eam &os, MatrixInterface <Tconst &
    matrix);
    protected:
    virtual void PrintDebugMessa ge(ostream &os) const= 0;

    };

    template<typena me DataType>
    ostream & operator<<(ostr eam &os, MatrixInterface <DataTypecons t
    &matrix)
    {
    matrix.PrintDeb ugMessage(os);
    return os;
    }
    /*************** *************** ******
    ** Simple Matrix
    *************** *************** *******/
    template<typena me DataType>
    class SimpleMatrix:pu blic MatrixInterface <DataType>
    {
    public:
    SimpleMatrix();
    SimpleMatrix(si ze_t nrow, size_t ncol);
    virtual ~SimpleMatrix() ;
    protected:

    virtual void PrintDebugMessa ge(ostream &os) const;

    size_t m_rowSize, m_colSize;
    DataType *m_data;


    };
    //
    //
    template<typena me DataType>
    SimpleMatrix<Da taType>::Simple Matrix()
    :m_rowSize(0), m_colSize(0),
    m_data(0)
    {
    }
    //
    //
    template<typena me DataType>
    SimpleMatrix<Da taType>::Simple Matrix(size_t nrow, size_t ncol)
    :m_rowSize(nrow ), m_colSize(ncol) ,
    m_data(0)
    {
    if(m_rowSize*m_ colSize>0) m_data =new
    DataType[m_rowSize*m_col Size];
    }
    //
    //
    template<typena me DataType>
    SimpleMatrix<Da taType>::~Simpl eMatrix()
    {
    if(m_data != 0) delete [] m_data;
    }
    //
    // Default PrintDebugMessa ge
    //
    template<typena me DataType>
    void SimpleMatrix<Da taType>::PrintD ebugMessage(ost ream &os) const
    {
    size_t index;
    cout << typeid(DataType ).name()<<"[ ";
    for(index = 0; index < m_rowSize*m_col Size; ++index)
    cout<<m_data[index]<<" ";
    cout << "]";
    }

    /*!!!!!!!!!!!!!! !!!!!!!!!!!!!!! !!!!!!!!!!!!!
    * I want PrintDebugMessa ge to behave differently
    * when I when the m_data submatrice of type = SimpleMatrix<Tw here T
    * can be anything.
    *
    * Doesn't work :(
    *
    !!!!!!!!!!!!!!! !!!!!!!!!!!!!!! !!!!!!!!!!!!*/

    /*
    template<typena me T>
    void SimpleMatrix< SimpleMatrix<T: :PrintDebugMess age(ostream &os)
    const
    {
    size_t index;
    cout << typeid(SimpleMa trix<int>).name ()<<"[[[[ ";
    for(index = 0; index < m_rowSize*m_col Size; ++index)
    cout<<m_data[index]<<" ";
    cout << "]]]]";
    }
    */


    /*!!!!!!!!!!!!!! !!!!!!!!!!!!!!! !!!!!!!!!!!!!
    * This works. Don't really get it.
    !!!!!!!!!!!!!!! !!!!!!!!!!!!!!! !!!!!!!!!!!!*/
    template<>
    void SimpleMatrix< SimpleMatrix<in t::PrintDebugMe ssage(ostream &os)
    const
    {
    size_t index;
    cout << "< "<<typeid(Simpl eMatrix<int>).n ame()<< " "<<"//** ";
    for(index = 0; index < m_rowSize*m_col Size; ++index)
    cout<<m_data[index]<<" ";
    cout << "**//";
    }




    /*************** ***
    *************** ***/
    int main(int argc, char **argv)
    {
    SimpleMatrix<in tIntMatrix(3,3) ;
    SimpleMatrix<do ubleDoubleMatri x(2,2);
    SimpleMatrix< SimpleMatrix<in t IntMatrixMatrix (2,2);
    SimpleMatrix< SimpleMatrix<do uble DoubleMatrixMat rix(2,2);
    cout<<IntMatrix <<endl;
    cout<<DoubleMat rix<<endl;
    cout<<IntMatrix Matrix<<endl;
    cout<<DoubleMat rixMatrix<<endl ; //use wrong Print function
    return 0;
    }

  • amparikh@gmail.com

    #2
    Re: Template member function help.


    Jason wrote:
    /*
    I have never use template before, so bear with me.
    >
    Here is what I am trying to do:
    >
    I declare an abstract base class MatrixInterface with template to
    define an interface for all my subsequent Matrix class. In
    MatrixInterface class, I overloaded the << operator by calling a pure
    virtual function PrintDebugMessa ge(ostream &os); then I can implement
    the function on individual Matrix classes later.
    >
    I create a Matrix class called SimpleMatrix, and implemented
    PrintDebugMessa ge(). Everthing works great until I want to implement
    different behavior depending whether it's
    >
    template<typena me DataTypevoid
    SimpleMatrix<Da taType>::PrintD ebugMessage(... ); //this is fine
    >
    or
    >
    //error
    template<typena me DataTypevoid SimpleMatrix< SimpleMatrix<Da taType>
    ::PrintDebugMes sage(...);
    >
    I want to print out data differently if a instance of my SimpleMatrix
    is a collection of sub-matrices of type SimpleMatrix. However, I can't
    get that to work.
    >
    If I sepcialize the template parameter like:
    >
    // works, but now only when submatrices has type of SimpleMatrix<in t>
    template<void SimpleMatrix< SimpleMatrix<in t>
    ::PrintDebugMes sage(...);
    >
    then it works. How I generalize the function above to handle
    SimpleMatrice submatrix of all type?
    >
    >
    Below is a sample code of my problem. It compiles on gcc 3.2.3 and
    intel c++ 8.1
    */
    /*************** *************** **************
    >
    *************** *************** **************/
    #include <iostream>
    #include <typeinfo>
    >
    using namespace std;
    >
    /*************** *************** ******
    ** ABC for all Matrix class
    *************** *************** *******/
    template<typena me DataType>
    class MatrixInterface
    {
    public:
    template<typena me T>
    friend ostream & operator<<(ostr eam &os, MatrixInterface <Tconst &
    matrix);
    protected:
    virtual void PrintDebugMessa ge(ostream &os) const= 0;
    >
    };
    >
    template<typena me DataType>
    ostream & operator<<(ostr eam &os, MatrixInterface <DataTypecons t
    &matrix)
    {
    matrix.PrintDeb ugMessage(os);
    return os;
    }
    /*************** *************** ******
    ** Simple Matrix
    *************** *************** *******/
    template<typena me DataType>
    class SimpleMatrix:pu blic MatrixInterface <DataType>
    {
    public:
    SimpleMatrix();
    SimpleMatrix(si ze_t nrow, size_t ncol);
    virtual ~SimpleMatrix() ;
    protected:
    >
    virtual void PrintDebugMessa ge(ostream &os) const;
    >
    size_t m_rowSize, m_colSize;
    DataType *m_data;
    >
    >
    };
    //
    //
    template<typena me DataType>
    SimpleMatrix<Da taType>::Simple Matrix()
    :m_rowSize(0), m_colSize(0),
    m_data(0)
    {
    }
    //
    //
    template<typena me DataType>
    SimpleMatrix<Da taType>::Simple Matrix(size_t nrow, size_t ncol)
    :m_rowSize(nrow ), m_colSize(ncol) ,
    m_data(0)
    {
    if(m_rowSize*m_ colSize>0) m_data =new
    DataType[m_rowSize*m_col Size];
    }
    //
    //
    template<typena me DataType>
    SimpleMatrix<Da taType>::~Simpl eMatrix()
    {
    if(m_data != 0) delete [] m_data;
    }
    //
    // Default PrintDebugMessa ge
    //
    template<typena me DataType>
    void SimpleMatrix<Da taType>::PrintD ebugMessage(ost ream &os) const
    {
    size_t index;
    cout << typeid(DataType ).name()<<"[ ";
    for(index = 0; index < m_rowSize*m_col Size; ++index)
    cout<<m_data[index]<<" ";
    cout << "]";
    }
    >
    /*!!!!!!!!!!!!!! !!!!!!!!!!!!!!! !!!!!!!!!!!!!
    * I want PrintDebugMessa ge to behave differently
    * when I when the m_data submatrice of type = SimpleMatrix<Tw here T
    * can be anything.
    *
    * Doesn't work :(
    *
    !!!!!!!!!!!!!!! !!!!!!!!!!!!!!! !!!!!!!!!!!!*/
    >
    /*
    template<typena me T>
    void SimpleMatrix< SimpleMatrix<T: :PrintDebugMess age(ostream &os)
    const
    {
    size_t index;
    cout << typeid(SimpleMa trix<int>).name ()<<"[[[[ ";
    for(index = 0; index < m_rowSize*m_col Size; ++index)
    cout<<m_data[index]<<" ";
    cout << "]]]]";
    }
    */
    >
    >
    /*!!!!!!!!!!!!!! !!!!!!!!!!!!!!! !!!!!!!!!!!!!
    * This works. Don't really get it.
    !!!!!!!!!!!!!!! !!!!!!!!!!!!!!! !!!!!!!!!!!!*/
    template<>
    void SimpleMatrix< SimpleMatrix<in t::PrintDebugMe ssage(ostream &os)
    const
    {
    size_t index;
    cout << "< "<<typeid(Simpl eMatrix<int>).n ame()<< " "<<"//** ";
    for(index = 0; index < m_rowSize*m_col Size; ++index)
    cout<<m_data[index]<<" ";
    cout << "**//";
    }
    >
    >
    >
    >
    /*************** ***
    *************** ***/
    int main(int argc, char **argv)
    {
    SimpleMatrix<in tIntMatrix(3,3) ;
    SimpleMatrix<do ubleDoubleMatri x(2,2);
    SimpleMatrix< SimpleMatrix<in t IntMatrixMatrix (2,2);
    SimpleMatrix< SimpleMatrix<do uble DoubleMatrixMat rix(2,2);
    cout<<IntMatrix <<endl;
    cout<<DoubleMat rix<<endl;
    cout<<IntMatrix Matrix<<endl;
    cout<<DoubleMat rixMatrix<<endl ; //use wrong Print function
    return 0;
    }

    Well, you first need to either explicity partially specialize the class
    for that type(SimpleMati rx<Tand then use PrintDebugMessa ge the way
    you have used it.

    Remember the class is a template class. PrintDebugMessa fe is NOT a
    member template.

    Comment

    • amparikh@gmail.com

      #3
      Re: Template member function help.


      Jason wrote:
      /*
      I have never use template before, so bear with me.
      >
      Here is what I am trying to do:
      >
      I declare an abstract base class MatrixInterface with template to
      define an interface for all my subsequent Matrix class. In
      MatrixInterface class, I overloaded the << operator by calling a pure
      virtual function PrintDebugMessa ge(ostream &os); then I can implement
      the function on individual Matrix classes later.
      >
      I create a Matrix class called SimpleMatrix, and implemented
      PrintDebugMessa ge(). Everthing works great until I want to implement
      different behavior depending whether it's
      >
      template<typena me DataTypevoid
      SimpleMatrix<Da taType>::PrintD ebugMessage(... ); //this is fine
      >
      or
      >
      //error
      template<typena me DataTypevoid SimpleMatrix< SimpleMatrix<Da taType>
      ::PrintDebugMes sage(...);
      >
      I want to print out data differently if a instance of my SimpleMatrix
      is a collection of sub-matrices of type SimpleMatrix. However, I can't
      get that to work.
      >
      If I sepcialize the template parameter like:
      >
      // works, but now only when submatrices has type of SimpleMatrix<in t>
      template<void SimpleMatrix< SimpleMatrix<in t>
      ::PrintDebugMes sage(...);
      >
      then it works. How I generalize the function above to handle
      SimpleMatrice submatrix of all type?
      >
      >
      Below is a sample code of my problem. It compiles on gcc 3.2.3 and
      intel c++ 8.1
      */
      /*************** *************** **************
      >
      *************** *************** **************/
      #include <iostream>
      #include <typeinfo>
      >
      using namespace std;
      >
      /*************** *************** ******
      ** ABC for all Matrix class
      *************** *************** *******/
      template<typena me DataType>
      class MatrixInterface
      {
      public:
      template<typena me T>
      friend ostream & operator<<(ostr eam &os, MatrixInterface <Tconst &
      matrix);
      protected:
      virtual void PrintDebugMessa ge(ostream &os) const= 0;
      >
      };
      >
      template<typena me DataType>
      ostream & operator<<(ostr eam &os, MatrixInterface <DataTypecons t
      &matrix)
      {
      matrix.PrintDeb ugMessage(os);
      return os;
      }
      /*************** *************** ******
      ** Simple Matrix
      *************** *************** *******/
      template<typena me DataType>
      class SimpleMatrix:pu blic MatrixInterface <DataType>
      {
      public:
      SimpleMatrix();
      SimpleMatrix(si ze_t nrow, size_t ncol);
      virtual ~SimpleMatrix() ;
      protected:
      >
      virtual void PrintDebugMessa ge(ostream &os) const;
      >
      size_t m_rowSize, m_colSize;
      DataType *m_data;
      >
      >
      };
      //
      //
      template<typena me DataType>
      SimpleMatrix<Da taType>::Simple Matrix()
      :m_rowSize(0), m_colSize(0),
      m_data(0)
      {
      }
      //
      //
      template<typena me DataType>
      SimpleMatrix<Da taType>::Simple Matrix(size_t nrow, size_t ncol)
      :m_rowSize(nrow ), m_colSize(ncol) ,
      m_data(0)
      {
      if(m_rowSize*m_ colSize>0) m_data =new
      DataType[m_rowSize*m_col Size];
      }
      //
      //
      template<typena me DataType>
      SimpleMatrix<Da taType>::~Simpl eMatrix()
      {
      if(m_data != 0) delete [] m_data;
      }
      //
      // Default PrintDebugMessa ge
      //
      template<typena me DataType>
      void SimpleMatrix<Da taType>::PrintD ebugMessage(ost ream &os) const
      {
      size_t index;
      cout << typeid(DataType ).name()<<"[ ";
      for(index = 0; index < m_rowSize*m_col Size; ++index)
      cout<<m_data[index]<<" ";
      cout << "]";
      }
      >
      /*!!!!!!!!!!!!!! !!!!!!!!!!!!!!! !!!!!!!!!!!!!
      * I want PrintDebugMessa ge to behave differently
      * when I when the m_data submatrice of type = SimpleMatrix<Tw here T
      * can be anything.
      *
      * Doesn't work :(
      *
      !!!!!!!!!!!!!!! !!!!!!!!!!!!!!! !!!!!!!!!!!!*/
      >
      /*
      template<typena me T>
      void SimpleMatrix< SimpleMatrix<T: :PrintDebugMess age(ostream &os)
      const
      {
      size_t index;
      cout << typeid(SimpleMa trix<int>).name ()<<"[[[[ ";
      for(index = 0; index < m_rowSize*m_col Size; ++index)
      cout<<m_data[index]<<" ";
      cout << "]]]]";
      }
      */
      >
      >
      /*!!!!!!!!!!!!!! !!!!!!!!!!!!!!! !!!!!!!!!!!!!
      * This works. Don't really get it.
      !!!!!!!!!!!!!!! !!!!!!!!!!!!!!! !!!!!!!!!!!!*/
      template<>
      void SimpleMatrix< SimpleMatrix<in t::PrintDebugMe ssage(ostream &os)
      const
      {
      size_t index;
      cout << "< "<<typeid(Simpl eMatrix<int>).n ame()<< " "<<"//** ";
      for(index = 0; index < m_rowSize*m_col Size; ++index)
      cout<<m_data[index]<<" ";
      cout << "**//";
      }
      >
      >
      >
      >
      /*************** ***
      *************** ***/
      int main(int argc, char **argv)
      {
      SimpleMatrix<in tIntMatrix(3,3) ;
      SimpleMatrix<do ubleDoubleMatri x(2,2);
      SimpleMatrix< SimpleMatrix<in t IntMatrixMatrix (2,2);
      SimpleMatrix< SimpleMatrix<do uble DoubleMatrixMat rix(2,2);
      cout<<IntMatrix <<endl;
      cout<<DoubleMat rix<<endl;
      cout<<IntMatrix Matrix<<endl;
      cout<<DoubleMat rixMatrix<<endl ; //use wrong Print function
      return 0;
      }

      Well, you first need to either explicity partially specialize the class
      for that type(SimpleMati rx<Tand then use PrintDebugMessa ge the way
      you have used it.

      Remember the class is a template class. PrintDebugMessa ge is NOT a
      member template.

      Comment

      • Victor Bazarov

        #4
        Re: Template member function help.

        Jason wrote:
        /*
        I have never use template before, so bear with me.
        >
        Here is what I am trying to do:
        >
        I declare an abstract base class MatrixInterface with template to
        define an interface for all my subsequent Matrix class. In
        MatrixInterface class, I overloaded the << operator by calling a pure
        virtual function PrintDebugMessa ge(ostream &os); then I can implement
        the function on individual Matrix classes later.
        >
        I create a Matrix class called SimpleMatrix, and implemented
        PrintDebugMessa ge(). Everthing works great until I want to implement
        different behavior depending whether it's
        >
        template<typena me DataTypevoid
        SimpleMatrix<Da taType>::PrintD ebugMessage(... ); //this is fine
        >
        or
        >
        //error
        template<typena me DataTypevoid SimpleMatrix< SimpleMatrix<Da taType>
        >>>PrintDebugMe ssage(...);
        [..]
        What you're trying here is to specialise a member without specialising
        the class first. That's prohibited, AFAIK.

        Your solution lies either in specialising the entire class:

        #include <iostream>
        using namespace std;

        template<class Tstruct Blah {
        void out(ostream& os) {
        os << "regular Blah\n";
        }
        };

        template<class Tstruct Blah<Blah<T {
        void out(ostream& os) {
        os << "Blah of Blah\n";
        }
        };

        int main()
        {
        Blah<intbi;
        Blah<doublebd;
        Blah<Blah<int bbi;
        Blah<Blah<Blah< double bbbd;

        bi.out(cout);
        bd.out(cout);
        bbi.out(cout);
        bbbd.out(cout);
        }

        (which would require a whole lot of repetition) or in providing
        a proxy "printer" class and specialising it instead (look up "policy
        based design"):

        #include <iostream>
        using namespace std;

        template<class Tstruct Blah;

        template<class Tstruct Blah_Printer {
        static void out(ostream& os, Blah<T>& blah);
        };

        template<class Tstruct Blah {
        void out(ostream& os) {
        Blah_Printer<T> ::out(os, *this);
        }
        };

        template<class T>
        void Blah_Printer<T> ::out(ostream& os, Blah<T>& b) {
        os << "regular Blah\n";
        }

        // partial specialisation
        template<class Tstruct Blah_Printer<Bl ah<T {
        static void out(ostream& os, Blah<Blah<T& b) {
        os << "Blah of Blah\n";
        }
        };

        int main()
        {
        Blah<intbi;
        Blah<doublebd;
        Blah<Blah<int bbi;
        Blah<Blah<Blah< double bbbd;

        bi.out(cout);
        bd.out(cout);
        bbi.out(cout);
        bbbd.out(cout);
        }

        Of course, 'Blah<Blah<Blah <Blah<Blah... >' is treated just like the
        simply nested 'Blah<Blah<T' would be.

        V
        --
        Please remove capital 'A's when replying by e-mail
        I do not respond to top-posted replies, please don't ask


        Comment

        • Jason

          #5
          Re: Template member function help.



          On Oct 17, 10:58 am, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
          Jason wrote:
          /*
          I have never use template before, so bear with me.
          >
          Here is what I am trying to do:
          >
          I declare an abstract base class MatrixInterface with template to
          define an interface for all my subsequent Matrix class. In
          MatrixInterface class, I overloaded the << operator by calling a pure
          virtual function PrintDebugMessa ge(ostream &os); then I can implement
          the function on individual Matrix classes later.
          >
          I create a Matrix class called SimpleMatrix, and implemented
          PrintDebugMessa ge(). Everthing works great until I want to implement
          different behavior depending whether it's
          >
          template<typena me DataTypevoid
          SimpleMatrix<Da taType>::PrintD ebugMessage(... ); //this is fine
          >
          or
          >
          //error
          template<typena me DataTypevoid SimpleMatrix< SimpleMatrix<Da taType>
          >>PrintDebugMes sage(...);
          [..]What you're trying here is to specialise a member without specialising
          the class first. That's prohibited, AFAIK.
          >
          Your solution lies either in specialising the entire class:
          >
          #include <iostream>
          using namespace std;
          >
          template<class Tstruct Blah {
          void out(ostream& os) {
          os << "regular Blah\n";
          }
          };
          >
          template<class Tstruct Blah<Blah<T {
          void out(ostream& os) {
          os << "Blah of Blah\n";
          }
          };
          >
          int main()
          {
          Blah<intbi;
          Blah<doublebd;
          Blah<Blah<int bbi;
          Blah<Blah<Blah< double bbbd;
          >
          bi.out(cout);
          bd.out(cout);
          bbi.out(cout);
          bbbd.out(cout);
          }
          >
          (which would require a whole lot of repetition) or in providing
          a proxy "printer" class and specialising it instead (look up "policy
          based design"):
          >
          #include <iostream>
          using namespace std;
          >
          template<class Tstruct Blah;
          >
          template<class Tstruct Blah_Printer {
          static void out(ostream& os, Blah<T>& blah);
          };
          >
          template<class Tstruct Blah {
          void out(ostream& os) {
          Blah_Printer<T> ::out(os, *this);
          }
          };
          >
          template<class T>
          void Blah_Printer<T> ::out(ostream& os, Blah<T>& b) {
          os << "regular Blah\n";
          }
          >
          // partial specialisation
          template<class Tstruct Blah_Printer<Bl ah<T {
          static void out(ostream& os, Blah<Blah<T& b) {
          os << "Blah of Blah\n";
          }
          };
          >
          int main()
          {
          Blah<intbi;
          Blah<doublebd;
          Blah<Blah<int bbi;
          Blah<Blah<Blah< double bbbd;
          >
          bi.out(cout);
          bd.out(cout);
          bbi.out(cout);
          bbbd.out(cout);
          }
          >
          Of course, 'Blah<Blah<Blah <Blah<Blah... >' is treated just like the
          simply nested 'Blah<Blah<T' would be.
          >
          V
          --
          Please remove capital 'A's when replying by e-mail
          I do not respond to top-posted replies, please don't ask- Hide quoted text -- Show quoted text -


          To Victor,

          Thanks for the help! Your explanation clarify my confusion over
          template.

          Comment

          Working...