This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

GCC/EGCS TEMPLATE HELL


Hi,

Please forward this to the appropriate lists/people. I have tried
sending mail to gcc@gcc.gnu.org
And it bounced back with the following message:

Hi. This is the qmail-send program at egcs.cygnus.com.
I'm afraid I wasn't able to deliver your message to the following
addresses.
This is a permanent error; I've given up. Sorry it didn't work out.

<gcc@gcc.gnu.org>:

  Your mail server is listed in an RBL, so I will not accept mail from
you.
  You should contact your local mail administrators and get your mail
  server fixed.  For more information about my use of the RBLs, see
        http://gcc.gnu.org/lists.html

  The IP number that I'm denying mail from is 131.193.48.80
  The RBL that you're on is ORBS RBL.  See:
      http://www.orbs.org/verify.cgi?address=131.193.48.80
  for more information about this RBL and why you are on it.

What's the deal with GCC and Cygnus EGCS, it appears they have merged?
Hence their contact
information is somewhat messed up.

---------------------------------------------------------------------------------------------

I am trying to port some code over from Irix 6.5.3 that makes
substantial use of template features.

I have read just about every page I could find on the subject and have
tried each suggested method,

(specifically the hints given by cygnos at
http://egcs.cygnus.com/onlinedocs/gcc_5.html#SEC110).

Here's my specific problem:

I have one template declaration header file:

//      FILE NAME: Tc/TcAction.hxx
//      AUTHOR: Benjamin Goldstein
//      TIME: 11:14:16
//      DATE: 09/22/99
//      MODULE TYPE: Specification
//      COPYRIGHT (C) 1999 by Benjamin Goldstein
//      CLASS DECLARATIONS: Template Class TcAction<T>
//                           Template Class TcAction<T>::Handler

#ifndef TCACTION_HXX_
#define TCACTION_HXX_
//failed interface attempt
//#ifdef LINUX_POSIX
//#pragma interface "TcAction.hxx"
//#endif

#include <list>
using namespace std;

/** Abstract base template class for all Action classes.
    Clients must inherit from this class in order to define an Action.
*/
template <class T>
class TcAction
{
public:
    /** Nested class Handler.
        This class is a nested member class of each action class derived

        from TcAction.
        Action handlers are defined by inheriting from this nested
        class.
    */
    class Handler
    {
    public:
        /// Default Constructor. User can turn off automatic action
handling.
        Handler(bool autoRegister = true);
        /// Destructor
        virtual ~Handler() = 0;
        /** Pure virtual member function.
            This method must be implemented by each Action Handler.
            It is called whenever a broadcast occurs for a given action.

        */
        virtual int handleAction(const T& t) = 0;
    };
    /// Destructor
    virtual ~TcAction() = 0;
    /// This method will register an action handler for notification.
    static void addHandler(Handler* aHandler);
     /// This method will unregister an action handler.
    static void removeHandler(Handler* aHandler);
    /// This method will notify each registered action handler.
    void broadcast();
    /// Thread safe version of addHandler.
    static void ts_addHandler(Handler* aHandler);
    /// Thread safe version of removeHandler.
    static void ts_removeHandler(Handler* aHandler);

    void ts_broadcast();

protected:
    /** Constructor.
        This makes TcAction an abstract base class.
    */
    TcAction();
    // This method is called by broadcast to notify action handlers.
    static void notify(TcAction<T>* t);
    /// Thread safe version of notify.
    static void ts_notify(TcAction<T>* t);

private:
    /// This private attribute stores action handlers.
    static list<Handler*>  handlerRegistry;

};

#endif

One defintion file:

//      FILE NAME: Tc/TcAction.cxx
//      AUTHOR: Benjamin Goldstein
//      TIME: 11:14:16
//      DATE: 09/22/99
//      MODULE TYPE: Body
//      COPYRIGHT (C) 1999 by Benjamin Goldstein
//      CLASS DEFINITIONS: Template Class TcAction<T>
//                         Template Class TcAction<T>::Handler

#include <Tc/TcAction.hxx>
#include <TcUt/TcUtDebug.hxx>
#define TcAction_debug 1

template <class T>
list<TcAction<T>::Handler *> TcAction<T>::handlerRegistry;

// Class TcAction::Handler
template <class T>
TcAction<T>::Handler::Handler (bool autoRegister)
{
   if (autoRegister)
      TcAction<T>::addHandler(this);
}

template <class T>
TcAction<T>::Handler::~Handler()

{

}


//Class TcAction
template <class T>
TcAction<T>::TcAction()
{
}
template <class T>
TcAction<T>::~TcAction()
{
}
template <class T>
void
TcAction<T>::addHandler(Handler* aHandler)
{

    if (TcAction_debug && tandemDebug)
        TcUtDebug::debug.debugMsg("TcAction",
                          "TcAction",
                          "addHandler");
    handlerRegistry.push_back(aHandler);
}

template <class T>
void
TcAction<T>::notify(TcAction<T>* t)
{
    list<Handler*>::iterator i;
    for(i=handlerRegistry.begin(); i != handlerRegistry.end(); i++)
        (*i)->handleAction(*(T*) t);
}

template <class T>
void
TcAction<T>::removeHandler(Handler* aHandler)
{
    handlerRegistry.remove(aHandler);
}

template <class T>
void
TcAction<T>::broadcast()
{
    T::notify(this);
}

template <class T>
void
TcAction<T>::ts_addHandler(Handler* aHandler)
{
    // STUB do thread safe mutex
    handlerRegistry.push_back(aHandler);
}
template <class T>
void
TcAction<T>::ts_notify(TcAction<T>* t)
{
    // STUB do thread safe mutex
    list<Handler*>::iterator i;
    for(i=handlerRegistry.begin(); i != handlerRegistry.end(); i++)
        (*i)->handleEvent(*(T) t);
}
template <class T>
void
TcAction<T>::ts_removeHandler(Handler* aHandler)
{
    // STUB do thread safe mutex
    handlerRegistry.remove(aHandler);
}

template <class T>
void
TcAction<T>::ts_broadcast()
{
    // STUB
}

These files are compiled and desposited into a static library
(libtandem.a)

I will skip the include file details but here is the ccflags used and
compile lines

# Redhat Linux 6.0 flags
CCFLAGS = -DLINUX_POSIX -MMD -O -Wall -frepo -ansi

.cxx.o:
        $(CC) $(CCFLAGS) $(ALL_INC) -c $*.cxx

tandem: tc
        ar -ru $(TANDEM_SRC_DIR)/lib/libtandem.a $(OBJECTS);

I have written a driver to test implementation and instantiation of
these templates:

TestAction.hxx that implements the above templates. (I have also tried
physically placing

this header at the top of MainDriver.cxx with exactly the same results)

TestAction.hxx:

#include <Tc/TcAction.cxx>

class TestAction : public TcAction<TestAction>
{
public:
   const char *name;
   TestAction() : name("TestAction") {
   };
};

class TestActionHandler : public TestAction::Handler
{

public:
   TestActionHandler () {};
   virtual int handleAction(const TestAction &action) {

      cerr<<"Halelujah this action handler is notified of
"<<action.name;
      return 1;
   };
};

Finally MainDriver.cxx:

//Failed attempt

//#ifdef LINUX_POSIX
//#pragma implementation "TcAction.hxx"
//#endif

#include "TestAction.hxx"
#include <list>

//Attempt at explicit instanantation
//template class TcAction<TestAction>;
//template class TcAction<TestAction>::Handler;
//template void
TcAction<TestAction>::addHandler(TcAction<TestAction>::Handler *);

main ()
{
   TestActionHandler myHandler;
   TestAction action;
   action.broadcast();

}

------------------------

# driver Makefile
TANDEM_SRC_DIR = ../..

include ../../TANDEM_DEFINES.linux

driverobjs = MainDriver.o

TSTLIBS = $(TANDEM_SRC_DIR)/lib/libtandem.a

all: drivers

drivers: $(driverobjs)
        $(CC) -falt-external-templates -Woverloaded-virtual -o test
$(TSTLIBS) $(driverobjs) ;

clean :
        rm -f *.o core *.d *.rpo;

sinclude *.d;

---------------------------------

No matter what I have tried I still get the same undefined symbol
errors:

(driver build)

cd ~/TandemUpdates/work/tandem0.1a/src/Tc/drivers/
make all
g++ -DLINUX_POSIX -MMD -O -Wall -frepo -ansi -I../.. -Iusr/include/g++
-I/usr/local/CAVE/include -DOPENGL -c MainDriver.cxx
g++ -frepo -Woverloaded-virtual -o test ../../lib/libtandem.a
MainDriver.o ;
MainDriver.o: In function `main':
MainDriver.o(.text+0x12): undefined reference to
`TcAction<TestAction>::Handler::Handler(bool)'
MainDriver.o(.text+0x25): undefined reference to
`TcAction<TestAction>::TcAction(void)'
MainDriver.o(.text+0x3f): undefined reference to
`TcAction<TestAction>::broadcast(void)'
MainDriver.o(.text+0x57): undefined reference to
`TcAction<TestAction>::~TcAction(void)'
MainDriver.o(.text+0x6c): undefined reference to
`TcAction<TestAction>::Handler::~Handler(void)'
MainDriver.o(.text+0x7b): undefined reference to
`TcAction<TestAction>::~TcAction(void)'
MainDriver.o(.text+0x8b): undefined reference to
`TcAction<TestAction>::Handler::~Handler(void)'
MainDriver.o: In function `TestActionHandler type_info function':
MainDriver.o(.gnu.linkonce.t.__tf17TestActionHandler+0xd): undefined
reference to `TcAction<TestAction>::Handler type_info function'
MainDriver.o(.gnu.linkonce.t.__tf17TestActionHandler+0x12): undefined
reference to `TcAction<TestAction>::Handler type_info node'
MainDriver.o: In function `TestActionHandler::~TestActionHandler(void)':

MainDriver.o(.gnu.linkonce.t._._17TestActionHandler+0xa): undefined
reference to `TcAction<TestAction>::Handler::~Handler(void)'
MainDriver.o: In function `TestAction type_info function':
MainDriver.o(.gnu.linkonce.t.__tf10TestAction+0xd): undefined reference
to `TcAction<TestAction> type_info function'
MainDriver.o(.gnu.linkonce.t.__tf10TestAction+0x12): undefined reference

to `TcAction<TestAction> type_info node'
MainDriver.o: In function `TestAction::~TestAction(void)':
MainDriver.o(.gnu.linkonce.t._._10TestAction+0xa): undefined reference
to `TcAction<TestAction>::~TcAction(void)'
collect2: ld returned 1 exit status
make: *** [drivers] Error 1

Compilation exited abnormally with code 2 at Fri Oct  1 11:55:36

This is regardless of all options I have mentioned above, include
explicit instantions.

Is there anyway I can use egcs to compile this type of code without
merging all template header declaration and cxx definition

body files? This is currently unfeasible as I am trying to port a fairly

large framework.

One other small issue -- I am trying to get the same behavior as
-MDUpdate Makedepend flags on sgi compilers which dumps

all dependency information into one file. Right now I am using the -MMD
flag and have an sinclude *.d at the bottom of my make file.

Is this the correct?

Forgot a rather important piece of information ;) :
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/specs

gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release) on RedHat
Linux 6.0 using an updated 2.2.5-22 kernel release on
an Intel PII-366.

Thanks very much,

--
=====================================================================
Benjamin Goldstein                               benjamin@evl.uic.edu
Electronic Visualization Laboratory              Tel: (312) 996-3002
University of Illinois at Chicago                Fax: (312) 413-7585
http://www.evl.uic.edu/benjamin
=====================================================================



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]