Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

hideous template woes 1

Status
Not open for further replies.

DoraC

Programmer
May 7, 2002
98
US
hi,

I have a rudimentary stack-class implemented in C++ which was working fine until I decided to pull the declaration out into a header file. I now have two files - a header file and a definition file (also containing main()).

a snippet of the header is as follows:
Code:
template <class T>
class mSTACK
{
public:
...
    T pop();
...
protected:
    deque<T> dStack;
}
And a snippet of the definition is as:
Code:
...
template <typename T>
T mSTACK<typename T>::pop()
{
	T Tdata;
	if ( dStack.empty() )
	{
		throw ReadEmptyStack();
	};
	Tdata = dStack.back();
	dStack.pop_back();
	return Tdata;
}
...
int main()
{
    mSTACK<int>* csStack = new mSTACK<int>;
...
    int ia = 0;
    csStack->push( ia );
    cout << &quot;value1 is: .&quot; 
         << csStack->pop()
         << &quot;.&quot; 
         << endl;
and the unfortunate output is:
Code:
/out:mSTACK.exe 
mSTACK.obj 
libcp.lib(locale.obj) : error LNK2005: &quot;public: static class std::locale::id std::num_put<char,class std::ostreambuf_iterator<char,struct std::char_traits<char> > >::id&quot; (?id@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@2V0locale@2@A) already defined in mSTACK.obj
libcp.lib(locale.obj) : error LNK2005: &quot;public: static class std::locale::id std::numpunct<char>::id&quot; (?id@?$numpunct@D@std@@2V0locale@2@A) already defined in mSTACK.obj
mSTACK.exe : fatal error LNK1169: one or more multiply defined symbols found
So - again - this worked fine when the definition and declarations were together in one file (i.e. everything was inline). Something with how I'm defining my non-inline functions isn't ok, and after staring at it for a while I'm still not sure what it is.

thank you very much for any help,
dora c
 
it seems you have implemented in a .h a template instance to char(I mean char insteat ot T) and have #included this .h in many .cpp files. You should separate declaration by implementation. Put implementation in .cpp file and leave only declaration in the .h file.

Ion Filipski
1c.bmp
 
Hi,

I have simplified and isolated my code in an attempt to get to the root of this (frustrating) problem.

I have my template class
Code:
#include <deque>

using namespace std;

template <typename T>
class mSTACK
{
public:
    T pop()
    {
        T Tdata;
        Tdata = dStack.back();
        dStack.pop_back();
        return Tdata;
    };

    void push( T& rTinData )
    {
        T TData( rTinData );
        dStack.push_back( TData );
    };

protected:
    deque<T> dStack;
};
in its own file, which I &quot;object&quot; compiled (produced .obj file vs. .exe).

I defined a rudimentary header file:
Code:
#include <deque>

using namespace std;

template <typename T>
class mSTACK
{
public:

    T pop();
    void push( T& rTinData );

protected:

    deque<T> dStack;
};
to faciliate compilation (via a #include &quot;stack.h&quot;)
But, when I compile the .obj file with a .cpp file to produce a .exe (via VC++ 6.0 command-line compile, passing
stack.obj stack_user.cpp -o stack_user
I get:
Code:
/out:stack.exe 
/out:stack_user.exe 
stack.obj 
stack_user.obj 
stack_user.obj : error LNK2019: unresolved external symbol &quot;public: class qTest __thiscall mSTACK<class qTest>::pop(void)&quot; (?pop@?$mSTACK@VqTest@@@@QAE?AVqTest@@XZ) referenced in function _main
stack_user_test.obj : error LNK2019: unresolved external symbol &quot;public: void __thiscall mSTACK<class qTest>::push(class qTest &)&quot; (?push@?$mSTACK@VqTest@@@@QAEXAAVqTest@@@Z) referenced in function _main
stack_user.exe : fatal error LNK1120: 2 unresolved externals

(why is it trying to build a stack.exe file, and not just a stack_user.exe file? doesn't the -o option tell it to build an executable named whatever comes after the -o? Shouldn't this just compile the .obj file into whatever .cpp source I'm compiling, producing a complete executable? Something is really off here (in my understanding, I know)...

This does not happen if I follow the same procedure but with non-template classes.

This is very frustrating - what am I missing or doing wrong? This is a simplified version of something I'm doing for work. We unfortunately have no C++ people here, other than me.

ANy help *very* appreciated,
Thanks :,(
dora c
 
1. change #include<stack.h> to #include<stack>
2. remove any using namespace xxx from header files
3. any stl headers with extension .h change to filenames without extension, for example iostream.h change to iostream. Don't mix these files, they are not compatible.

Ion Filipski
1c.bmp
 
Read the FAQ at the C++: Unix forum.



Short answer:

It's not supposed to work. You can't separate a class template's interface from its implementation the same way you can with a class. They're simply not the same thing. You have to put them all in the one file unless you want to deal with explicit specializations and whatnot.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top