How to use template to create a library.

S

Sunny

Hi,
I want to create a library out of a C++ sources. The implementation
should be in object files and there will be a header file which the
client will #include. I want to use templates to implement the code.
This is the API in the header file:

void GenericQSort (T A[SIZE], int len);

and clients can call it like :

Mystring A[SIZE];
GenericQSort(A,size);

where Mystring is user defined data type where he should overload <
operator for comparison. If I define a template function for
GenericQSort, any change made to it will require clients to recompile
which I don't want. How should I implement GenericQSort?
Thanks
 
K

Kai-Uwe Bux

Sunny said:
Hi,
I want to create a library out of a C++ sources. The implementation
should be in object files and there will be a header file which the
client will #include. I want to use templates to implement the code.
This is the API in the header file:

void GenericQSort (T A[SIZE], int len);

and clients can call it like :

Mystring A[SIZE];
GenericQSort(A,size);

where Mystring is user defined data type where he should overload <
operator for comparison. If I define a template function for
GenericQSort, any change made to it will require clients to recompile
which I don't want. How should I implement GenericQSort?

a) Bad example: there already is std::sort.

b) Unless you (and all your clients) use a compiler that supports "export",
you implement templated functions and classes within the header files of
your library. If you cannot predict for which types the templates will be
instantiated, there is no other way: the template code has to be visible to
the client that is causing the instantiation.


Best

Kai-Uwe Bux
 
M

Michael Ekstrand

Hi,
I want to create a library out of a C++ sources. The implementation
should be in object files and there will be a header file which the
client will #include. I want to use templates to implement the code.
This is the API in the header file:

void GenericQSort (T A[SIZE], int len);

and clients can call it like :

Mystring A[SIZE];
GenericQSort(A,size);

where Mystring is user defined data type where he should overload <
operator for comparison. If I define a template function for
GenericQSort, any change made to it will require clients to recompile
which I don't want. How should I implement GenericQSort?
Thanks

You can't, unless you provide predefined template
instantiations of your GenericQSort for every type your users may attempt
to use GenericQSort on. In order to instantiate a template for a
particular set of parameters, the compiler must have the source for that
template. The compiler uses that source and generates a version of the
method specific to that set of parameters at compile time - it cannot
reference the source in another object file (unless the object file has
an explicit instantiation of the template over those parameters, and the
compiler knows that it's there via an extern declaration of the
instantiation).

- Michael
 
S

Sunny

Hi,
I want to create a library out of a C++ sources. The implementation
should be in object files and there will be a header file which the
client will #include. I want to use templates to implement the code.
This is the API in the header file:
void GenericQSort (T A[SIZE], int len);
and clients can call it like :
Mystring A[SIZE];
GenericQSort(A,size);
where Mystring is user defined data type where he should overload <
operator for comparison. If I define a template function for
GenericQSort, any change made to it will require clients to recompile
which I don't want. How should I implement GenericQSort?
Thanks

You can't, unless you provide predefined template
instantiations of your GenericQSort for every type your users may attempt
to use GenericQSort on. In order to instantiate a template for a
particular set of parameters, the compiler must have the source for that
template. The compiler uses that source and generates a version of the
method specific to that set of parameters at compile time - it cannot
reference the source in another object file (unless the object file has
an explicit instantiation of the template over those parameters, and the
compiler knows that it's there via an extern declaration of the
instantiation).

- Michael

OK. If I instantiate the template for a data type then it should work,
although for only that data type. Here is what I tried.
///file: a.hh
#ifndef __A_HH
#define __A_HH
template <typename T>
T sum(T a, T b)
{
return a+b;
}
#endif
///file a.cc
#include "a.hh"
template int sum<int>(int,int);

I compiled it and created a.o: g++ -c a.cc

Now I am trying to call sum in cl.cc

#include <iostream>
// I cannot #include a.hh because I don't want this file to be
recompiled if a.hh changes

using std::cout;
using std::endl;


int main()
{
int a = sum(4,5);
cout << a << endl;
return 0;
}

In this file what should I #include? I cannot #include a.hh. The
function implementation is present in a.o but how can I declare the
function here?
Thanks
 
M

Michael Ekstrand

In this file what should I #include? I cannot #include a.hh. The
function implementation is present in a.o but how can I declare the
function here?

You need to do one of two things: have 2 header files, or move your
template code into your .cpp. Here's what I have for your example:

/* BEGIN sum.hh */
template<typename T> T sum(T a, T b); // notice declaration only
extern template int sum<int>(int, int); // extern decl of instantiation
/* END sum.hh */

/* BEGIN sum.cc */
#include "tmpl.h" // probably don't actually need this

// define the template...
template<typename T> T sum(T a, T b)
{
return a+b;
}

// and instantiate it
template int sum<int>(int, int);
/* END sum.cc */

/* BEGIN main.cc */
#include "sum.hh"
#include <iostream>

int main()
{
std::cout <<"1 + 2 = " <<sum(1, 2) <<std::endl;
return 0;
}
/* END main.cc */

- Michael
 
S

Sunny

You need to do one of two things: have 2 header files, or move your
template code into your .cpp. Here's what I have for your example:

/* BEGIN sum.hh */
template<typename T> T sum(T a, T b); // notice declaration only
extern template int sum<int>(int, int); // extern decl of instantiation
/* END sum.hh */

/* BEGIN sum.cc */
#include "tmpl.h" // probably don't actually need this

// define the template...
template<typename T> T sum(T a, T b)
{
return a+b;

}

// and instantiate it
template int sum<int>(int, int);
/* END sum.cc */

/* BEGIN main.cc */
#include "sum.hh"
#include <iostream>

int main()
{
std::cout <<"1 + 2 = " <<sum(1, 2) <<std::endl;
return 0;}

/* END main.cc */

- Michael

Thanks for the code Michael. This solves my problem.
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top