Here's one for the STL gurus.  I'll start with the question I really
need answered, and then describe the background of my specific 
problem for anyone who is interested.

The question:

How do you handle STL template instantiation in a large,
multi-library program?

I have a large C++ program that exists as multiple libraries in
multiple directories.  It has templates of my own design.  I want to
start using STL in addition to my own template classes.  What is the
best way to compile and link so as to get the necessary template
instantiations without getting multiple copies of the template code
in every .o file that uses the templates? 

The background:

I'm running RedHat 5.2, kernel 2.2.1 on an alpha and compiling with
egcs version egcs-2.91.66 19990314 (egcs-1.1.2 release).  For the
last few years I've been developing a large C++ program as multiple
libraries in multiple directories.  Some of my classes and functions
are templates.  I compile everything with -fno-implicit-templates and
use explicit template instantiation.  Until now this has worked well
for me.

Now I want to learn and start using STL.  I started with a simple
standalone program, all of which was in a single file in a single
directory.  I compiled this WITHOUT -fno-implicit-templates and it
worked.   Now I am trying to link it to some of the libraries from
my big project, which are compiled WITH -fno-implicit-templates.  If
I compile the small test program with -fno-implicit-templates, I get
a zillion "undefined reference" errors from the linker, all of which
refer to stl classes and functions.  If I compile it without
-fno-implicit-templates, it compiles, links and runs, but this is
not a useful solution for my big program, since, as I understand
things, it would cause a lot of unnecessary object code bloat.

I tried explicit instantiation of the STL templates I thought my
program was using, but I could never get it to work.  It gave error
messages similar to the ones shown below for the next example.

Next I tried -frepo, which works fine for my big program (that does 
not yet use STL), but fails when I try to compile the test program 
that does use STL:

g++ -c -g -I../p38 -I../util -I../gold -I../jw -DALPHA -DMAKE_DATE="\"Mon Sep 13 
15:34:30 UTC 1999\""  -Werror -L../lib/alpha -frepo  stlsort.cc -o alpha/stlsort.o
g++ -g -I../p38 -I../util -I../gold -I../jw -DALPHA -DMAKE_DATE="\"Mon Sep 13 15:34:30 
UTC 1999\""  -Werror -L../lib/alpha -frepo alpha/stlsort.o -lp38 -lutil -lgold -ljw 
-lbsd -lcpml -lm  -o alpha/stlsort
alpha/stlsort.o: In function `sort__H2ZPP4JunkZPFPC4JunkPC4Junk_b_X01T0X11_v':
/usr/include/g++/stl_algo.h:1060: undefined reference to 
`__introsort_loop__H4ZPP4JunkZP4JunkZlZPFPC4JunkPC4Junk_b_X01T0PX11X21X31_v'
/usr/include/g++/stl_algo.h:1060: undefined reference to 
`__introsort_loop__H4ZPP4JunkZP4JunkZlZPFPC4JunkPC4Junk_b_X01T0PX11X21X31_v'
/usr/include/g++/stl_algo.h:1061: undefined reference to 
`__final_insertion_sort__H2ZPP4JunkZPFPC4JunkPC4Junk_b_X01T0X11_v'
/usr/include/g++/stl_algo.h:1061: undefined reference to 
`__final_insertion_sort__H2ZPP4JunkZPFPC4JunkPC4Junk_b_X01T0X11_v'
collect2: ld returned 1 exit status
make: *** [alpha/stlsort] Error 1

I am including the test program as an attachment.

If anyone has suggestions, or if you can just tell me how you handle
STL template instantiation in large multi-library programs, I would
be most grateful.

TIA,
Jack Wathey
/*---------------------------------------------------------------------
$Id: stlsort.cc,v 1.5 1999/09/13 14:19:04 jack Exp jack $
---------------------------------------------------------------------*/
/*
simple C++ test program
*/

#include <iostream.h>
#include <vector>
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <Timer.h>
using namespace std;


//---------------------------------------------------------------------
class Junk {
    static const int n_elements = 10000;
    int value;
    int *p_ints;

public:

    Junk( int i=0 ) : value( i ), p_ints(0) { 
        p_ints = new int[n_elements]; 
    }
    Junk( const Junk& original) 
    : value( original.value ), p_ints(0) { 
        p_ints = new int[n_elements];
        bcopy( original.p_ints, p_ints, n_elements*sizeof(int) );
    }

    friend bool junk_comp( const Junk* p1, const Junk* p2 );

    bool operator<( const Junk& rhs ) const {
        return( value < rhs.value );
    }
    Junk& operator=( int i ) {
        value = i;
        return *this;
    }
    Junk& operator=( const Junk& rhs ) {
        value = rhs.value;
        delete [] p_ints; 
        p_ints = new int[n_elements];
        bcopy( rhs.p_ints, p_ints, n_elements*sizeof(int) );
        return *this;
    }
    ~Junk(void) { delete [] p_ints; p_ints = 0; }
    friend ostream& operator<<( ostream& out, const Junk& junk );
};


bool 
//---------------------------------------------------------------------
junk_comp( const Junk* p1, const Junk* p2 )  {
    return( p1->value < p2->value );
}

ostream& 
//---------------------------------------------------------------------
operator<<( ostream& out, const Junk& junk ) {
    return( out << junk.value );
}

#if 0
template class vector<Junk>;
template void sort<Junk *>(Junk *, Junk *, bool (*)(const Junk *, const Junk *) );
#endif

#if 0
template class vector<Junk>;
template void sort<Junk *>(Junk *, Junk *);
template void fill<Junk *, Junk>(Junk *, Junk *, Junk const &);
template void __introsort_loop<Junk *, Junk, long>(Junk *, Junk *, Junk *,
long);
#endif





int 
//---------------------------------------------------------------------
main( int argc, char **argv ) {


  int i;
  vector<Junk*> j(2000);

  for(i=0; i<j.size(); i++) {
      j[i] = new Junk;
      *j[i] = rand();
  }

  cout << "Original contents of j:\n";
  for(i=0; i<j.size(); i++) {
    cout << *j[i] << " ";
  }
  cout << endl;
  Timer sort_time( "sort" );

  sort_time.start();
  sort(j.begin(), j.end(), junk_comp);
  sort_time.stop();

  cout << "Sorted contents of j:\n";
  for(i=0; i<j.size(); i++) {
    cout << *j[i] << " ";
  }
  cout << endl;

  Timer::write_all_timers();

  return 0;
}

Reply via email to