undefined external template fn?

Discussion in 'C++' started by .rhavin grobert, Jun 11, 2008.

  1. Hi group....;-)



    i have the following class....
    _____________________________________________________
    // QSharedReg.hpp

    typedef unsigned __int64 QUAD;
    using namespace boost;

    template<class T> struct _SQSRI {
    QUAD qID;
    shared_ptr<T> pItem;
    };


    template <class T> class CQSharedReg {
    public:
    CQSharedReg();
    virtual ~CQSharedReg();
    inline UINT Count() const {return m_vector.size();};
    shared_ptr<T> const Get(QUAD qID) const;
    shared_ptr<T> const GetByIdx(UINT nIdx) const;
    shared_ptr<T> Register(QUAD qID);
    bool Unregister(QUAD qID);

    private:
    std::vector<_SQSRI<T> > m_vector;
    };
    ________________________________________________________

    ....and the following implementation.....
    ________________________________________________________
    // QSharedReg.cpp

    //-----------------------------------------------------------------------------
    template <class T> CQSharedReg<T>::CQSharedReg() {}

    //-----------------------------------------------------------------------------
    template <class T> CQSharedReg<T>::~CQSharedReg() {}

    //-----------------------------------------------------------------------------
    template <class T> shared_ptr<T> const CQSharedReg<T>::Get(QUAD qID)
    const {
    register UINT nCnt = Count();
    _SQSRI<T> const* psqri;
    while (nCnt-->0) {
    psqri = &m_vector[nCnt];
    if (psqri == NULL)
    continue;
    if (psqri->qID != qID)
    continue;
    return psqri->pItem;
    }
    shared_ptr<T> none;
    return none;
    }

    //-----------------------------------------------------------------------------
    template <class T> shared_ptr<T> const CQSharedReg<T>::GetByIdx(UINT
    nIdx) const {
    if (nIdx >= m_vector.size()) {
    shared_ptr<T> none;
    return none;
    }
    return m_vector[nIdx].pItem;
    }

    //-----------------------------------------------------------------------------
    template <class T> shared_ptr<T> CQSharedReg<T>::Register(QUAD qID) {
    shared_ptr<T> pItem = (shared_ptr<T>) Get(qID);
    if (pItem.get() != NULL)
    return pItem;
    _SQSRI<T> sqri;
    sqri.pItem = new T;
    sqri.qID = qID;
    m_vector.push_back(sqri);
    return sqri.pItem;
    }

    //-----------------------------------------------------------------------------
    template <class T> bool CQSharedReg<T>::Unregister(QUAD qID) {
    register UINT nCnt = Count();
    _SQSRI<T>* psqri;
    while (nCnt-->0) {
    psqri = &m_vector[nCnt];
    if (psqri == NULL)
    continue;
    if (psqri->qID != qID)
    continue;
    m_vector.erase(psqri);
    return true;
    }
    return false;
    }
    ________________________________________________________

    the object "QSharedReg.obj" compiles fine (is there anything to
    compile!?) but when i instatiate it in another class (here in class
    CQElement using) ....

    ________________________________________________________
    // from QElement.hpp
    CQSharedReg<CQDetail> m_rDetails;

    // from QElement.cpp

    UINT nCnt = m_rDetails.Count();
    shared_ptr<CQDetail> pDetail3 = m_rDetails.Register(3);
    nCnt = m_rDetails.Count();
    shared_ptr<CQDetail> pDetail5 = m_rDetails.Register(5);
    nCnt = m_rDetails.Count();
    if (pDetail5.get() != NULL) {
    shared_ptr<CQDetail> pDetail1 = m_rDetails.Register(1);
    nCnt = m_rDetails.Count();
    }
    nCnt = m_rDetails.Count();


    ________________________________________________________

    ....., i get the following error (name-mangling skipped): ...

    QElement.obj : error LNK2001: unresolved external symbol "public:
    virtual __thiscall CQSharedReg<class CQDetail>::~CQSharedReg<class
    CQDetail>(void)"
    QElement.obj : error LNK2001: unresolved external symbol "public:
    class boost::shared_ptr<class CQDetail> __thiscall CQSharedReg<class
    CQDetail>::Register(unsigned __int64)"
    QElement.obj : error LNK2001: unresolved external symbol "public:
    __thiscall CQSharedReg<class CQDetail>::CQSharedReg<class
    CQDetail>(void)"

    ....so if i interpret it right, the linker tries for example to find a
    function
    CQSharedReg<class CQDetail>::~CQSharedReg<class CQDetail>(void)
    but that function IS defined...

    Any help apreciated, TIA, -.rhavin;)
    .rhavin grobert, Jun 11, 2008
    #1
    1. Advertising

  2. On Jun 11, 8:26 am, ".rhavin grobert" <> wrote:
    > Hi group....;-)
    >
    > i have the following class....
    > _____________________________________________________
    > // QSharedReg.hpp
    >
    > typedef unsigned __int64 QUAD;
    > using namespace boost;
    >
    > template<class T> struct _SQSRI {
    >         QUAD           qID;
    >         shared_ptr<T>  pItem;
    >
    > };
    >
    > template <class T> class CQSharedReg {
    > public:
    >         CQSharedReg();
    >         virtual ~CQSharedReg();
    >         inline UINT         Count() const {return m_vector..size();};
    >         shared_ptr<T> const Get(QUAD qID) const;
    >         shared_ptr<T> const GetByIdx(UINT nIdx) const;
    >         shared_ptr<T>       Register(QUAD qID);
    >         bool                Unregister(QUAD qID);
    >
    > private:
    >         std::vector<_SQSRI<T> > m_vector;};
    >
    > ________________________________________________________
    >
    > ...and the following implementation.....
    > ________________________________________________________
    > // QSharedReg.cpp
    >
    > //-------------------------------------------------------------------------­----
    > template <class T> CQSharedReg<T>::CQSharedReg() {}
    >
    > //-------------------------------------------------------------------------­----
    > template <class T> CQSharedReg<T>::~CQSharedReg() {}
    >
    > //-------------------------------------------------------------------------­----
    > template <class T> shared_ptr<T> const CQSharedReg<T>::Get(QUAD qID)
    > const {
    >         register UINT nCnt = Count();
    >         _SQSRI<T> const* psqri;
    >         while (nCnt-->0) {
    >                 psqri = &m_vector[nCnt];
    >                 if (psqri == NULL)
    >                         continue;
    >                 if (psqri->qID != qID)
    >                         continue;
    >                 return psqri->pItem;
    >         }
    >         shared_ptr<T> none;
    >         return none;
    >
    > }
    >
    > //-------------------------------------------------------------------------­----
    > template <class T> shared_ptr<T> const CQSharedReg<T>::GetByIdx(UINT
    > nIdx) const {
    >         if (nIdx >= m_vector.size()) {
    >                 shared_ptr<T> none;
    >                 return none;
    >         }
    >         return m_vector[nIdx].pItem;
    >
    > }
    >
    > //-------------------------------------------------------------------------­----
    > template <class T> shared_ptr<T> CQSharedReg<T>::Register(QUAD qID) {
    >         shared_ptr<T> pItem = (shared_ptr<T>) Get(qID);
    >         if (pItem.get() != NULL)
    >                 return pItem;
    >         _SQSRI<T> sqri;
    >         sqri.pItem = new T;
    >         sqri.qID   = qID;
    >         m_vector.push_back(sqri);
    >         return sqri.pItem;
    >
    > }
    >
    > //-------------------------------------------------------------------------­----
    > template <class T> bool CQSharedReg<T>::Unregister(QUAD qID) {
    >         register UINT nCnt = Count();
    >         _SQSRI<T>* psqri;
    >         while (nCnt-->0) {
    >                 psqri = &m_vector[nCnt];
    >                 if (psqri == NULL)
    >                         continue;
    >                 if (psqri->qID != qID)
    >                         continue;
    >                 m_vector.erase(psqri);
    >                 return true;
    >         }
    >         return false;}
    >
    > ________________________________________________________
    >
    > the object "QSharedReg.obj" compiles fine (is there anything to
    > compile!?) but when i instatiate it in another class (here in class
    > CQElement using) ....
    >
    > ________________________________________________________
    > // from QElement.hpp
    >         CQSharedReg<CQDetail> m_rDetails;
    >
    > // from QElement.cpp
    >
    >         UINT nCnt = m_rDetails.Count();
    >         shared_ptr<CQDetail> pDetail3 = m_rDetails.Register(3);
    >         nCnt = m_rDetails.Count();
    >         shared_ptr<CQDetail> pDetail5 = m_rDetails.Register(5);
    >         nCnt = m_rDetails.Count();
    >         if (pDetail5.get() != NULL) {
    >                 shared_ptr<CQDetail> pDetail1 = m_rDetails.Register(1);
    >                 nCnt = m_rDetails.Count();
    >         }
    >         nCnt = m_rDetails.Count();
    >
    > ________________________________________________________
    >
    > ...., i get the following error (name-mangling skipped): ...
    >
    > QElement.obj : error LNK2001: unresolved external symbol "public:
    > virtual __thiscall CQSharedReg<class CQDetail>::~CQSharedReg<class
    > CQDetail>(void)"
    > QElement.obj : error LNK2001: unresolved external symbol "public:
    > class boost::shared_ptr<class CQDetail> __thiscall CQSharedReg<class
    > CQDetail>::Register(unsigned __int64)"
    > QElement.obj : error LNK2001: unresolved external symbol "public:
    > __thiscall CQSharedReg<class CQDetail>::CQSharedReg<class
    > CQDetail>(void)"
    >
    > ...so if i interpret it right, the linker tries for example to find a
    > function
    > CQSharedReg<class CQDetail>::~CQSharedReg<class CQDetail>(void)
    > but that function IS defined...
    >
    > Any help apreciated, TIA, -.rhavin;)


    Are the namespaces same for both of them ?
    suresh shenoy, Jun 11, 2008
    #2
    1. Advertising

  3. On 11 Jun., 15:06, suresh shenoy <> wrote:
    > On Jun 11, 8:26 am, ".rhavin grobert" <> wrote:
    >
    >
    >
    > > Hi group....;-)

    >
    > > i have the following class....
    > > _____________________________________________________
    > > // QSharedReg.hpp

    >
    > > typedef unsigned __int64 QUAD;
    > > using namespace boost;

    >
    > > template<class T> struct _SQSRI {
    > > QUAD qID;
    > > shared_ptr<T> pItem;

    >
    > > };

    >
    > > template <class T> class CQSharedReg {
    > > public:
    > > CQSharedReg();
    > > virtual ~CQSharedReg();
    > > inline UINT Count() const {return m_vector.size();};
    > > shared_ptr<T> const Get(QUAD qID) const;
    > > shared_ptr<T> const GetByIdx(UINT nIdx) const;
    > > shared_ptr<T> Register(QUAD qID);
    > > bool Unregister(QUAD qID);

    >
    > > private:
    > > std::vector<_SQSRI<T> > m_vector;};

    >
    > > ________________________________________________________

    >
    > > ...and the following implementation.....
    > > ________________________________________________________
    > > // QSharedReg.cpp

    >
    > > //-------------------------------------------------------------------------­----
    > > template <class T> CQSharedReg<T>::CQSharedReg() {}

    >
    > > //-------------------------------------------------------------------------­----
    > > template <class T> CQSharedReg<T>::~CQSharedReg() {}

    >
    > > //-------------------------------------------------------------------------­----
    > > template <class T> shared_ptr<T> const CQSharedReg<T>::Get(QUAD qID)
    > > const {
    > > register UINT nCnt = Count();
    > > _SQSRI<T> const* psqri;
    > > while (nCnt-->0) {
    > > psqri = &m_vector[nCnt];
    > > if (psqri == NULL)
    > > continue;
    > > if (psqri->qID != qID)
    > > continue;
    > > return psqri->pItem;
    > > }
    > > shared_ptr<T> none;
    > > return none;

    >
    > > }

    >
    > > //-------------------------------------------------------------------------­----
    > > template <class T> shared_ptr<T> const CQSharedReg<T>::GetByIdx(UINT
    > > nIdx) const {
    > > if (nIdx >= m_vector.size()) {
    > > shared_ptr<T> none;
    > > return none;
    > > }
    > > return m_vector[nIdx].pItem;

    >
    > > }

    >
    > > //-------------------------------------------------------------------------­----
    > > template <class T> shared_ptr<T> CQSharedReg<T>::Register(QUAD qID) {
    > > shared_ptr<T> pItem = (shared_ptr<T>) Get(qID);
    > > if (pItem.get() != NULL)
    > > return pItem;
    > > _SQSRI<T> sqri;
    > > sqri.pItem = new T;
    > > sqri.qID = qID;
    > > m_vector.push_back(sqri);
    > > return sqri.pItem;

    >
    > > }

    >
    > > //-------------------------------------------------------------------------­----
    > > template <class T> bool CQSharedReg<T>::Unregister(QUAD qID) {
    > > register UINT nCnt = Count();
    > > _SQSRI<T>* psqri;
    > > while (nCnt-->0) {
    > > psqri = &m_vector[nCnt];
    > > if (psqri == NULL)
    > > continue;
    > > if (psqri->qID != qID)
    > > continue;
    > > m_vector.erase(psqri);
    > > return true;
    > > }
    > > return false;}

    >
    > > ________________________________________________________

    >
    > > the object "QSharedReg.obj" compiles fine (is there anything to
    > > compile!?) but when i instatiate it in another class (here in class
    > > CQElement using) ....

    >
    > > ________________________________________________________
    > > // from QElement.hpp
    > > CQSharedReg<CQDetail> m_rDetails;

    >
    > > // from QElement.cpp

    >
    > > UINT nCnt = m_rDetails.Count();
    > > shared_ptr<CQDetail> pDetail3 = m_rDetails.Register(3);
    > > nCnt = m_rDetails.Count();
    > > shared_ptr<CQDetail> pDetail5 = m_rDetails.Register(5);
    > > nCnt = m_rDetails.Count();
    > > if (pDetail5.get() != NULL) {
    > > shared_ptr<CQDetail> pDetail1 = m_rDetails.Register(1);
    > > nCnt = m_rDetails.Count();
    > > }
    > > nCnt = m_rDetails.Count();

    >
    > > ________________________________________________________

    >
    > > ...., i get the following error (name-mangling skipped): ...

    >
    > > QElement.obj : error LNK2001: unresolved external symbol "public:
    > > virtual __thiscall CQSharedReg<class CQDetail>::~CQSharedReg<class
    > > CQDetail>(void)"
    > > QElement.obj : error LNK2001: unresolved external symbol "public:
    > > class boost::shared_ptr<class CQDetail> __thiscall CQSharedReg<class
    > > CQDetail>::Register(unsigned __int64)"
    > > QElement.obj : error LNK2001: unresolved external symbol "public:
    > > __thiscall CQSharedReg<class CQDetail>::CQSharedReg<class
    > > CQDetail>(void)"

    >
    > > ...so if i interpret it right, the linker tries for example to find a
    > > function
    > > CQSharedReg<class CQDetail>::~CQSharedReg<class CQDetail>(void)
    > > but that function IS defined...

    >
    > > Any help apreciated, TIA, -.rhavin;)

    >
    > Are the namespaces same for both of them ?


    yes...
    .rhavin grobert, Jun 11, 2008
    #3
  4. .rhavin grobert

    Kai-Uwe Bux Guest

    ..rhavin grobert wrote:

    > Hi group....;-)
    >
    >
    >
    > i have the following class....
    > _____________________________________________________
    > // QSharedReg.hpp
    >
    > typedef unsigned __int64 QUAD;
    > using namespace boost;
    >
    > template<class T> struct _SQSRI {
    > QUAD qID;
    > shared_ptr<T> pItem;
    > };
    >
    >
    > template <class T> class CQSharedReg {
    > public:
    > CQSharedReg();
    > virtual ~CQSharedReg();
    > inline UINT Count() const {return m_vector.size();};
    > shared_ptr<T> const Get(QUAD qID) const;
    > shared_ptr<T> const GetByIdx(UINT nIdx) const;
    > shared_ptr<T> Register(QUAD qID);
    > bool Unregister(QUAD qID);
    >
    > private:
    > std::vector<_SQSRI<T> > m_vector;
    > };
    > ________________________________________________________
    >
    > ...and the following implementation.....
    > ________________________________________________________
    > // QSharedReg.cpp
    >

    [snip]
    >
    > ...., i get the following error (name-mangling skipped): ...
    >
    > QElement.obj : error LNK2001: unresolved external symbol "public:
    > virtual __thiscall CQSharedReg<class CQDetail>::~CQSharedReg<class
    > CQDetail>(void)"
    > QElement.obj : error LNK2001: unresolved external symbol "public:
    > class boost::shared_ptr<class CQDetail> __thiscall CQSharedReg<class
    > CQDetail>::Register(unsigned __int64)"
    > QElement.obj : error LNK2001: unresolved external symbol "public:
    > __thiscall CQSharedReg<class CQDetail>::CQSharedReg<class
    > CQDetail>(void)"
    >
    > ...so if i interpret it right, the linker tries for example to find a
    > function
    > CQSharedReg<class CQDetail>::~CQSharedReg<class CQDetail>(void)
    > but that function IS defined...
    >
    > Any help apreciated, TIA, -.rhavin;)


    The short answer is: put the template definition into the header. For a
    longer account, see the FAQ:

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



    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Jun 11, 2008
    #4
  5. On Jun 11, 7:26 am, ".rhavin grobert" <> wrote:
    > Hi group....;-)
    >
    > i have the following class....
    > _____________________________________________________
    > // QSharedReg.hpp
    >
    > typedef unsigned __int64 QUAD;
    > using namespace boost;
    >
    > template<class T> struct _SQSRI {
    > QUAD qID;
    > shared_ptr<T> pItem;
    >
    > };
    >
    > template <class T> class CQSharedReg {
    > public:
    > CQSharedReg();
    > virtual ~CQSharedReg();
    > inline UINT Count() const {return m_vector.size();};
    > shared_ptr<T> const Get(QUAD qID) const;
    > shared_ptr<T> const GetByIdx(UINT nIdx) const;
    > shared_ptr<T> Register(QUAD qID);
    > bool Unregister(QUAD qID);
    >
    > private:
    > std::vector<_SQSRI<T> > m_vector;};
    >
    > ________________________________________________________
    >
    > ...and the following implementation.....
    > ________________________________________________________
    > // QSharedReg.cpp
    >
    > //-----------------------------------------------------------------------------
    > template <class T> CQSharedReg<T>::CQSharedReg() {}
    >
    > //-----------------------------------------------------------------------------
    > template <class T> CQSharedReg<T>::~CQSharedReg() {}
    >
    > //-----------------------------------------------------------------------------
    > template <class T> shared_ptr<T> const CQSharedReg<T>::Get(QUAD qID)
    > const {
    > register UINT nCnt = Count();
    > _SQSRI<T> const* psqri;
    > while (nCnt-->0) {
    > psqri = &m_vector[nCnt];
    > if (psqri == NULL)
    > continue;
    > if (psqri->qID != qID)
    > continue;
    > return psqri->pItem;
    > }
    > shared_ptr<T> none;
    > return none;
    >
    > }
    >
    > //-----------------------------------------------------------------------------
    > template <class T> shared_ptr<T> const CQSharedReg<T>::GetByIdx(UINT
    > nIdx) const {
    > if (nIdx >= m_vector.size()) {
    > shared_ptr<T> none;
    > return none;
    > }
    > return m_vector[nIdx].pItem;
    >
    > }
    >
    > //-----------------------------------------------------------------------------
    > template <class T> shared_ptr<T> CQSharedReg<T>::Register(QUAD qID) {
    > shared_ptr<T> pItem = (shared_ptr<T>) Get(qID);
    > if (pItem.get() != NULL)
    > return pItem;
    > _SQSRI<T> sqri;
    > sqri.pItem = new T;
    > sqri.qID = qID;
    > m_vector.push_back(sqri);
    > return sqri.pItem;
    >
    > }
    >
    > //-----------------------------------------------------------------------------
    > template <class T> bool CQSharedReg<T>::Unregister(QUAD qID) {
    > register UINT nCnt = Count();
    > _SQSRI<T>* psqri;
    > while (nCnt-->0) {
    > psqri = &m_vector[nCnt];
    > if (psqri == NULL)
    > continue;
    > if (psqri->qID != qID)
    > continue;
    > m_vector.erase(psqri);
    > return true;
    > }
    > return false;}
    >
    > ________________________________________________________
    >
    > the object "QSharedReg.obj" compiles fine (is there anything to
    > compile!?) but when i instatiate it in another class (here in class
    > CQElement using) ....
    >
    > ________________________________________________________
    > // from QElement.hpp
    > CQSharedReg<CQDetail> m_rDetails;
    >
    > // from QElement.cpp
    >
    > UINT nCnt = m_rDetails.Count();
    > shared_ptr<CQDetail> pDetail3 = m_rDetails.Register(3);
    > nCnt = m_rDetails.Count();
    > shared_ptr<CQDetail> pDetail5 = m_rDetails.Register(5);
    > nCnt = m_rDetails.Count();
    > if (pDetail5.get() != NULL) {
    > shared_ptr<CQDetail> pDetail1 = m_rDetails.Register(1);
    > nCnt = m_rDetails.Count();
    > }
    > nCnt = m_rDetails.Count();
    >
    > ________________________________________________________
    >
    > ...., i get the following error (name-mangling skipped): ...
    >
    > QElement.obj : error LNK2001: unresolved external symbol "public:
    > virtual __thiscall CQSharedReg<class CQDetail>::~CQSharedReg<class
    > CQDetail>(void)"
    > QElement.obj : error LNK2001: unresolved external symbol "public:
    > class boost::shared_ptr<class CQDetail> __thiscall CQSharedReg<class
    > CQDetail>::Register(unsigned __int64)"
    > QElement.obj : error LNK2001: unresolved external symbol "public:
    > __thiscall CQSharedReg<class CQDetail>::CQSharedReg<class
    > CQDetail>(void)"
    >
    > ...so if i interpret it right, the linker tries for example to find a
    > function
    > CQSharedReg<class CQDetail>::~CQSharedReg<class CQDetail>(void)
    > but that function IS defined...
    >
    > Any help apreciated, TIA, -.rhavin;)


    AFAIK, you cannot have a template declared in one file and the
    implementation on anther one, unless the "export" keyword is used. But
    (again AFAIK) there's only one compiler that implements
    "export" (can't remember it's name).

    Just a thought.
    Fernando Gómez, Jun 11, 2008
    #5
  6. .rhavin grobert

    Triple-DES Guest

    On 12 Jun, 00:22, Fernando Gómez <> wrote:
    > AFAIK, you cannot have a template declared in one file and the
    > implementation on anther one, unless the "export" keyword is used.


    You could, but you would have to include the definitions somehow. It
    is pretty standard to write the definitions in a .tpp file (or
    similar), and then #include this file in the header file.

    Of course, from the compiler's POV it would not be much different from
    a single file.

    > But (again AFAIK) there's only one compiler that implements
    > "export" (can't remember it's name).
    >
    > Just a thought.


    Comeau has 'export'. I think Intel C++ has it too. (Since they're both
    based on EDG's front end)

    DP
    Triple-DES, Jun 12, 2008
    #6
    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. Scott J. McCaughrin

    static data-member undefined external

    Scott J. McCaughrin, Nov 9, 2004, in forum: C++
    Replies:
    8
    Views:
    512
    Victor Bazarov
    Nov 19, 2004
  2. Mantorok Redgormor
    Replies:
    70
    Views:
    1,754
    Dan Pop
    Feb 17, 2004
  3. dede
    Replies:
    6
    Views:
    136
    A. Sinan Unur
    Dec 21, 2004
  4. VK
    Replies:
    45
    Views:
    595
    Dr John Stockton
    Sep 12, 2006
  5. -Lost
    Replies:
    13
    Views:
    372
    Richard Cornford
    Jan 31, 2007
Loading...

Share This Page