moving template implementation to cpp

U

U.Mutlu

This is about a template linking problem:

Below we have a struct TS1, a template class TC1 and a non-template class TC2.
TC2::f() calls TC1<TS1>::f(), it compiles, but linker brings error.
I don't understand why, normally it should work I think.

Why must one place template code in header file?
What's the reason the following doesn't link?
I would like to hide the iplementation by doing it in the cpp file.
Is there a workaround to get this compiled+linked?


//-------- inc.hpp -------------
struct TS1
{
};

struct TS2
{
};

template<typename T = TS1> class TC1
{
public:
TC1();
void f();
};
extern TC1<> gC1;

class TC2
{
public:
TC2();
void f();
};


//-------- file1.cpp -----------
#include "inc.hpp"

template<typename T> TC1<T>::TC1()
{
}

template<typename T> void TC1<T>::f()
{
}

TC1<> gC1;

int main(int argc, char* argv[])
{
TC2 C2;
C2.f();

return 0;
}


//-------- file2.cpp -----------
#include "inc.hpp"

TC2::TC2()
{
}

void TC2::f()
{
gC1.f();
}


## Build g++: g++ file1.cpp file2.cpp
## Build MSC++: cl file1.cpp file2.cpp
 
U

U.Mutlu

LR wrote, On 02/04/12 06:51:
U.Mutlu said:
Why must one place template code in header file?

Maybe this will help.

[35.12] Why can't I separate the definition of my templates class from
its declaration and put it inside a .cpp file?

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

Thanks.
I now found the following IMHO acceptable solution to the/my problem:

//----- file: inc.hpp ------------------------------------------------
/* Moving template implementation out of header file.

Hiding implementation details by moving it into the cpp file.
The method below (see esp. file1.cpp) should be put into the
C++ FAQ under 35.12 and 35.13.
This method as shown here works for the defaulting typename,
but one can add more types in a similar fashion as shown in file1.cpp.

Author: U.Mutlu (www.mutluit.com)

Build g++: g++ file1.cpp file2.cpp main.cpp
Build MSC++: cl file1.cpp file2.cpp main.cpp
*/

struct TS1
{
};

struct TS2
{
};

// implementation in file1.cpp
template<typename T = TS1> class TC1
{
public:
TC1();
void f();
};
extern TC1<> gC1;


// implementation in file2.cpp
class TC2
{
public:
TC2();
void f(); // inside it makes call to gC1.f() (just for testing)
};


//----- file: file1.cpp ----------------------------------------------
#include "inc.hpp"

template<typename T> TC1<T>::TC1()
{
}

template<typename T> void TC1<T>::f()
{
}

// SOLUTION OF THE (LINK-) PROBLEM: specialize (instantiate) it
// for the desired type (or types, by repeating it for each type):
template<> TC1<TS1>::TC1()
{
}

template<> void TC1<TS1>::f()
{
}


//----- file: file2.cpp ----------------------------------------------
#include "inc.hpp"

TC2::TC2()
{
}

void TC2::f()
{
gC1.f();
}


//----- file: main.cpp -----------------------------------------------
#include "inc.hpp"

// test application:

TC1<> gC1;

int main(int argc, char* argv[])
{
TC2 C2;
C2.f();

return 0;
}
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top