template in error

Discussion in 'C++' started by eiji, Jan 14, 2006.

  1. eiji

    eiji Guest

    Hi folks,

    I have a linker - problem using a Matrix-template.
    Maybe someone can help me with that.

    Q:
    "using femath::Matrix" or "using femath::Matrix<double>";

    Consider this:

    ##########################
    namespace femath {
    ....
    template<class T> class Matrix
    {
    public:
    Matrix();
    Matrix(int rows);
    Matrix(int rows, int columns);
    virtual ~Matrix();
    ....
    };
    } //end namespace

    namespace fesolv {

    using femath::Matrix;

    class AbstractSolver
    {
    public:
    AbstractSolver(Model* model);
    virtual ~AbstractSolver();

    public:
    virtual void Solve()=0;
    ....
    protected:
    Model* _model;
    Matrix<double>* _systemstiffnessmatrix;
    ....
    };

    } //end namespace

    ##########################

    Everything compiles great but the linker tells me:
    AbstractSolver.obj : error LNK2019: unresolved external symbol "public:
    __thiscall femath::Matrix<double>::Matrix<double>(int)"
    (??0?$Matrix@N@femath@@QAE@H@Z) referenced in function "public:
    __thiscall fesolv::AbstractSolver::AbstractSolver(class fesolv::Model
    *)" (??0AbstractSolver@fesolv@@QAE@PAVModel@1@@Z)
    ......

    I'm using VC++2005 and there is no external *.lib.
    Matrix<class T> is in the same compile/link-unit.

    Thanks a lot,
    Sascha
     
    eiji, Jan 14, 2006
    #1
    1. Advertising

  2. eiji wrote:
    > Hi folks,
    >
    > I have a linker - problem using a Matrix-template.
    > Maybe someone can help me with that.
    >
    > Q:
    > "using femath::Matrix" or "using femath::Matrix<double>";


    using femath::Matrix;

    >
    > Consider this:
    >
    > ##########################
    > namespace femath {
    > ...
    > template<class T> class Matrix
    > {
    > public:
    > Matrix();
    > Matrix(int rows);
    > Matrix(int rows, int columns);
    > virtual ~Matrix();
    > ...
    > };
    > } //end namespace
    >
    > namespace fesolv {
    >
    > using femath::Matrix;
    >
    > class AbstractSolver
    > {
    > public:
    > AbstractSolver(Model* model);
    > virtual ~AbstractSolver();
    >
    > public:
    > virtual void Solve()=0;
    > ...
    > protected:
    > Model* _model;
    > Matrix<double>* _systemstiffnessmatrix;
    > ...
    > };
    >
    > } //end namespace
    >
    > ##########################
    >
    > Everything compiles great but the linker tells me:
    > AbstractSolver.obj : error LNK2019: unresolved external symbol "public:
    > __thiscall femath::Matrix<double>::Matrix<double>(int)"


    The constructor
    template<typename T> Matrix<T>::Matrix(int);
    is not implemented ...

    > (??0?$Matrix@N@femath@@QAE@H@Z) referenced in function "public:
    > __thiscall fesolv::AbstractSolver::AbstractSolver(class fesolv::Model
    > *)" (??0AbstractSolver@fesolv@@QAE@PAVModel@1@@Z)


    .... and it is called from the constructor of fesolv::AbstractSolver.

    Regards, Stephan
     
    =?iso-8859-1?q?Stephan_Br=F6nnimann?=, Jan 14, 2006
    #2
    1. Advertising

  3. eiji

    eiji Guest

    That is clear. The constructor is called but not found. So why?
    template<class T> Matrix<T>::Matrix(int)
    {
    ...
    }
    exists!

    Is there a "template<T>" phrase missing?
    What can be the problem?
     
    eiji, Jan 14, 2006
    #3
  4. eiji

    TB Guest

    eiji sade:
    > That is clear. The constructor is called but not found. So why?
    > template<class T> Matrix<T>::Matrix(int)
    > {
    > ...
    > }
    > exists!
    >


    But where?

    > Is there a "template<T>" phrase missing?
    > What can be the problem?
    >


    TB
     
    TB, Jan 14, 2006
    #4
  5. eiji

    eiji Guest

    I tried this:

    //main.cpp
    namespace test {

    template<class T> class Test
    {
    T i;
    public:
    Test(T t);

    };

    template<class T> Test<T>::Test(T t)
    {
    i = t;
    }

    }
    int main(int argc , char *argv[])
    {
    using namespace test;
    Test<int> T(1);
    return 0;
    }
    #######

    Compiles and links without problems!

    but handling it this way:
    #######
    //a.h
    namespace test {

    template<class T> class Test
    {
    T i;
    public:
    Test(T t);

    };
    }
    #####
    //a.cpp
    #include "a.h"
    namespace test {

    template<class T> Test<T>::Test(T t)
    {
    i = t;
    }

    }
    //main.cpp
    #include "a.h"
    int main(int argc , char *argv[])
    {
    using namespace test;
    Test<int> T(1);
    return 0;
    }

    same error, the constructor is not found!
    Any important linker-options?

    Sorry, any suggestions?
    Sascha
     
    eiji, Jan 14, 2006
    #5
  6. eiji

    TB Guest

    eiji sade:
    > I tried this:

    <snip>
    > but handling it this way:
    > #######
    > //a.h
    > namespace test {
    >
    > template<class T> class Test
    > {
    > T i;
    > public:
    > Test(T t);
    >
    > };
    > }
    > #####
    > //a.cpp
    > #include "a.h"
    > namespace test {
    >
    > template<class T> Test<T>::Test(T t)
    > {
    > i = t;
    > }
    >
    > }

    <snip>
    >
    > same error, the constructor is not found!
    > Any important linker-options?
    >
    > Sorry, any suggestions?
    > Sascha
    >


    Compiler limitations. The template declarations and definitions must
    be in the same translation unit.

    Other solutions:
    * Read about support for the 'export'-keyword for you compiler.
    * #include the cpp-file after the declarations in the header-file.

    TB
     
    TB, Jan 14, 2006
    #6
  7. eiji

    Ben Pope Guest

    eiji wrote:
    > Hi folks,
    >
    > I have a linker - problem using a Matrix-template.
    > Maybe someone can help me with that.



    class Model;

    namespace femath {
    template<class T> class Matrix
    {
    public:
    Matrix();
    Matrix(int rows);
    Matrix(int rows, int columns);
    virtual ~Matrix();
    };
    } //end namespace

    namespace fesolv {

    using femath::Matrix;

    class AbstractSolver
    {
    public:
    AbstractSolver(Model* model);
    virtual ~AbstractSolver();

    public:
    virtual void Solve()=0;
    protected:
    Model* model_;
    Matrix<double>* systemstiffnessmatrix_;
    };
    }

    int main(int argc, char* argv[])
    {
    }

    Works for me.

    Ben Pope
    --
    I'm not just a number. To many, I'm known as a string...
     
    Ben Pope, Jan 14, 2006
    #7
  8. eiji

    eiji Guest

    TB schrieb:

    >
    > Compiler limitations. The template declarations and definitions must
    > be in the same translation unit.
    >
    > Other solutions:
    > * Read about support for the 'export'-keyword for you compiler.
    > * #include the cpp-file after the declarations in the header-file.
    >
    > TB


    Most of the linker errors I have solved with that(declaration and
    definition in the same translation unit). One more to go(link
    operator). This is nearly the same problem.

    Please Consider this:
    #####################
    namespace femath {

    template<class T> class Matrix
    {
    public:
    Matrix();
    ...
    friend std::valarray<T> operator*(const Matrix& A, const
    std::valarray<T>& b);
    ...
    };
    ....
    template<class T> std::valarray<T> operator*(const Matrix<T>& A, const
    std::valarray<T>& b)
    {
    ...
    }
    };

    typedef std::valarray<double> DoubleVector;

    void LinearSolver::ComputeSystemReactionVector()
    {

    Matrix<double>* tempStiffness = new Matrix<double>;
    ...
    DoubleVector* uglob = new DoubleVector(0.0,dimension);
    ...
    (*_reactionforce) = (*tempStiffness)*(*uglob);

    delete uglob;
    delete tempStiffness;
    }
    #####################
    Error message:
    LinearSolver.obj : error LNK2019: unresolved external symbol "class
    std::valarray<double> __cdecl femath::eek:perator*(class
    femath::Matrix<double> const &,class std::valarray<double> const &)"
    (??Dfemath@@YA?AV?$valarray@N@std@@ABV?$Matrix@N@0@ABV12@@Z) referenced
    in function "private: void __thiscall
    fesolv::LinearSolver::ComputeSystemReactionVector(void)"
    (?ComputeSystemReactionVector@LinearSolver@fesolv@@AAEXXZ)
    #####################

    The code works fine before translating Matrix into a template. The
    operator works as expected.
    Now the operator is not found during linkage. There must be one reason
    why the definition is not accepted, but the declaration does.

    Regards,
    Sascha
     
    eiji, Jan 14, 2006
    #8
  9. eiji

    Ben Pope Guest

    eiji wrote:
    > I tried this:
    >
    > //main.cpp
    > namespace test {
    >
    > template<class T> class Test
    > {
    > T i;
    > public:
    > Test(T t);
    >
    > };
    >
    > template<class T> Test<T>::Test(T t)
    > {
    > i = t;
    > }
    >
    > }
    > int main(int argc , char *argv[])
    > {
    > using namespace test;
    > Test<int> T(1);
    > return 0;
    > }
    > #######
    >
    > Compiles and links without problems!
    >
    > but handling it this way:
    > #######
    > //a.h
    > namespace test {
    >
    > template<class T> class Test
    > {
    > T i;
    > public:
    > Test(T t);
    >
    > };
    > }
    > #####
    > //a.cpp
    > #include "a.h"
    > namespace test {
    >
    > template<class T> Test<T>::Test(T t)
    > {
    > i = t;
    > }
    >
    > }
    > //main.cpp
    > #include "a.h"
    > int main(int argc , char *argv[])
    > {
    > using namespace test;
    > Test<int> T(1);
    > return 0;
    > }
    >
    > same error, the constructor is not found!
    > Any important linker-options?


    Test is a template, so the compiler must be able to see the definition.

    http://www.parashift.com/c -faq-lite/templates.html#faq-35.12

    Ben Pope
    --
    I'm not just a number. To many, I'm known as a string...
     
    Ben Pope, Jan 14, 2006
    #9
  10. eiji

    eiji Guest

    > Test is a template, so the compiler must be able to see the definition.
    >
    > http://www.parashift.com/c -faq-lite/templates.html#faq-35.12
    >
    > Ben Pope


    Thanks Ben, great link!
    ################
    //pre-declare each template friend function, add <> in the friend
    lines
    template<class T> class Matrix;
    template<class T> std::valarray<T> operator* (const Matrix<T>& A, const
    std::valarray<T>& b);
    template<class T> Matrix<T> operator*(const Matrix<T>& A, const
    Matrix<T>& B);

    template<class T> class Matrix
    {
    public:
    ...
    friend std::valarray<T> operator* <> (const Matrix& A, const
    std::valarray<T>& b);
    friend Matrix operator* <> (const Matrix& A, const Matrix& B);
    ...
    };
    ################

    Works fine!
    Thank you all for a lesson on template-programming :)
     
    eiji, Jan 14, 2006
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Theis
    Replies:
    2
    Views:
    495
    Chris Theis
    Jul 24, 2003
  2. tom_usenet
    Replies:
    0
    Views:
    560
    tom_usenet
    Jul 24, 2003
  3. Replies:
    1
    Views:
    2,142
    Gianni Mariani
    Jun 8, 2007
  4. Peng Yu
    Replies:
    3
    Views:
    802
    Thomas J. Gritzan
    Oct 26, 2008
  5. nguillot
    Replies:
    5
    Views:
    551
Loading...

Share This Page