[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::c_plus_plus

Title:C++
Notice:Read 1.* and use keywords (e.g. SHOW KEY/FULL KIT_CXX_VAX_VMS)
Moderator:DECCXX::AMARTIN
Created:Fri Nov 06 1987
Last Modified:Thu Jun 05 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:3604
Total number of notes:18242

3545.0. "template instatiation for functions not called directly" by AZUR::ANTEUNIS (If it's possible it's not interesting) Mon Apr 21 1997 13:22

Hi folks,

I run in to some (compilation flags ?) troubles, using DEC C++ V5.5-004 on
Digital UNIX V3.2G

it goes like this

my.hxx

  template <class T>
  void func (const class T & thing, void * arg)
  {
   ...
  }


my.cxx


  RWTvalSlist <T> nice_list;

  struct some_struct {....} userarg, *argp;

  argp = &userarg;

  nice_list.apply (func, (void *)argp);


What happens:


  typechecking is marvellous !! the compiler apparently instantiates
  the correct func. 

  but ld complains: 
    ld:
    Unresolved:
    Dump_List_Element(ArgumentSpecHandle&, void*)

  of course I use -Hf instead of -c, for all other switches I use the default

So I'm forces to explicitly instantiate Dump_List_Element; who is used by
but not called by Dump_List which happens to be also a template function.

the .apply member function is in some RogueWave library. It will actually call
(after manual instantiation) the correct function.



What am I doing wrong ?


dirk
  
T.RTitleUserPersonal
Name
DateLines
3545.1DECC::FOLTANMon Apr 21 1997 20:4412
I think I need a bit more information.  Can you provide an 
example of how Dump_List_Element is actually used 
by Dump_List and also how Dump_List is instantiated?
Does your application have a specialization of 
Dump_List_Element(ArgumentSpecHandle&, void*) at all?

Thanks,

Lois D. Foltan
DEC C++ Development

3545.2Here some source code fragmentsAZUR::ANTEUNISIf it's possible it's not interestingTue Apr 22 1997 08:09136
Lois,

both Dump_List and Dump_List_Element are instantiated for at least 5 classes
(for the time being, manually). 



Here the contents of Dump_List.hxx :
====================================

#ifndef _DUMP_THINGS_HXX_
#define _DUMP_THINGS_HXX_

#include <rw/tvslist.h>

class Dump_RWTValList_Arg
{
public: 
      const char *	pref_;
      const int		lvl_;

  Dump_RWTValList_Arg(const char *p, const int i) : pref_(p),lvl_(i) {};
};


template <class SomeHandle>
void Dump_List_Element
      (SomeHandle & 	element,
       void *			arg)
{
  Dump_RWTValList_Arg *dump_arg = (Dump_RWTValList_Arg *)arg;

  element.dumpThis(dump_arg->pref_, dump_arg->lvl_);
}

template <class SomeHandle>
void Dump_List
      (const RWTValSlist<SomeHandle> &	list,
       const char *			pref,
       const int			lvl)
{
  Dump_RWTValList_Arg	dump_arg (pref, lvl);

  RWTValSlist<SomeHandle> tmp;
  tmp = list;

  if (list.entries())
    tmp.apply (Dump_List_Element, (void *)&dump_arg);
  else
    cout << pref << " is an empty list." << endl;

  //  The following seems to be needed to instantiate the template
  //
  //if (0) Dump_List_Element(SomeHandle(), (void *)0);
  //
  // we changed it by #pragma define_template  in the appropriate .cxx file
  //
}

#endif /* _DUMP_THINGS_HXX_ */


Here an extract from a (test) program :
=======================================

  arg.setVariableName ("dismissed");

  a.addArgumentSpec (arg);   // a contans a list of ArgumentSpec
  a.dumpThis("a",FULL_DUMP); // this dumps a, including the list
 

Here the code of a.dumpThis() :
===============================

void EventSpecHandle::dumpThis (const char *arg, const int lvl) const
{
  const char *pref, *classname = "::EventSpec.";
  if (arg) pref = arg;
  else     pref = "";

  cout << pref << classname << "rep_ = " << rep_ ;

  if (rep_)
    {
      cout << "   refcount = " << rep_->getRefCount() << endl;
      if (lvl == DUMP_REP_ONLY) return;

      cout << pref << classname << "name_         = " << rep_->name_         <<
endl;
      cout << pref << classname << "variableName_ = " << rep_->variableName_ <<
endl;
      cout << pref << classname << "sign_         = " << rep_->sign_         <<
endl;
      cout << pref << classname << "comment_      = " << rep_->comment_      <<
endl;

      RWCString tmp(pref); tmp += classname;

      tmp += "argumentSpecs_";

      Dump_List (rep_->argumentSpecs_, (const char *)tmp,
		 DUMP_PROPAGATE_lvl(lvl));
    }

  else
    cout << endl;
}

#pragma define_template compareKey<EventSpecHandle>

#pragma define_template Dump_List<EventSpecHandle>
#pragma define_template Dump_List_Element<EventSpecHandle>


The 3 pragma's are not for ArgumentSpec but for EventSpec; EventSpec contains
a list of ArgumentSpec.   Some other objects contain a list of EventSpec, that
is why I instantiate the 3 functions on EventSpec.  ArgumentSpec.cxx contains a
similar constuction, that's what templates are about, no ?


As I said in my note, Dump_List is instantiated automatically.
Dump_List_Element is NOT.  The compiler gives me error messages, in case the
signature of the template for Dump_List_Element does not match what is needed.

The only difference the I notcie is that the code contains a real call to
Dump_List while it does not contain one to Dump_List_Element. Only the address
of the function is used.

The function compareKey has a similar problem. Also, the code does not contain a
call to that function, only it's address is passed into the RogueWave library.



Thanks for looking at my problem,

dirk
3545.3DECC::FOLTANTue Apr 22 1997 18:2610
Hi Dirk,

I have narrowed it down a bit.  Can you provide me
with one more piece of information.  The class
definition for RWTValSlist.  I would like to see
how the "apply" member function is defined.

Thanks,

Lois
3545.4AZUR::ANTEUNISIf it's possible it's not interestingWed Apr 23 1997 13:4915
Hi Lois,

I have made a tar file of /usr/include/rw with lots of things in it.

The starting point are the files

   tvslist.h
   tvslist.cc

Then it starts including the whole world, xvslist, rwslist...

The documentation is on  http://mybaby.vbo.dec.com/rogue/toolscr/classref.htm
if that would be of any use.

Dirk
3545.5Here a sample program (approx hundred lines)AZUR::ANTEUNISIf it's possible it's not interestingWed Apr 23 1997 15:04167
Lois,

cut along the ============ lines into the filenames indicated, then do the 
folloing build procedure:


rm *.o
rm -R cxx_repository
cxx -Hf SimpleBuffer.cxx
cxx -Hf DifferentBuffer.cxx
cxx -Hf function_pointers.cxx
cxx -o function_pointers *.o

The answer I get is:

ld:
Unresolved:
func(SimpleBuffer&, void*)
func(DifferentBuffer&, void*)


From where my question in .0 "what am I doing wrong ?"

Dirk



========================== templates.hxx ================================
#ifndef _TEMPLATES_
#define _TEMPLATES_

#include <iostream.h>


struct Counter
  { 
    char	letter;
    unsigned	count;
  };

template <class T>
void callforw (T & thing)
{
  if (thing.letters_to_be_counted)
    {
      struct Counter	arg;
      char *		l;

      for (l = thing.letters_to_be_counted; *l; l++)
	{
	  arg.letter = *l;
	  arg.count  = 0;

	  thing.apply (func, (void *)&arg);

	  cout << "There are " << arg.count 
	       << " " << *l << "'s in thing" <<endl;
	}
    }
}

template <class T>
void func (T & thing, void *arg)
{
  struct Counter * real_arg = (struct Counter *)arg;
  char * p;

  for (p = thing.buffer; p && *p; p++)
    {
      if (*p == real_arg->letter) real_arg->count += 1;
    }
}

#endif

========================== SimpleBuffer.hxx ================================
#include "templates.hxx"

class SimpleBuffer
{
public:
  char	 buffer[100];
  char * letters_to_be_counted;

  void apply (void (* f)(SimpleBuffer &, void *), void *);
};


class OtherBuffer : public SimpleBuffer
{
public:
  int	 	  some;
  float  	  other;
  struct Counter  fields;
};

========================== SimpleBuffer.cxx ================================
#include "SimpleBuffer.hxx"
#include "templates.hxx"

void SimpleBuffer::apply (void (* f)(SimpleBuffer &, void *),
			  void *arg)
{
  f (*this, arg);
}


========================== DifferentBuffer.hxx ================================
#include "templates.hxx"

class DifferentBuffer
{
public:
  int    total_count;
  char * letters_to_be_counted;
  char * letters_to_be_ignored;
  char	 buffer[100];

  void apply (void (* f)(DifferentBuffer &, void *), void *);
};


========================== DifferentBuffer.cxx ================================
#include "DifferentBuffer.hxx"
#include "templates.hxx"

void DifferentBuffer::apply (void (* f)(DifferentBuffer &, void *),
			     void *arg)
{
  f (*this, arg);
}

========================= function_pointers.cxx ==============================
#include <iostream.h>
#include <string.h>


#include "SimpleBuffer.hxx"
#include "DifferentBuffer.hxx"


#define VOWELS	"aeiouy"

main()
{
  SimpleBuffer	    simple;
  OtherBuffer	    other;
  DifferentBuffer   different;

  strcpy (simple.buffer, "some simple string");
  simple.letters_to_be_counted = VOWELS;

  strcpy (other.buffer, "abcdefghijklmnopqrstuvwxyz");
  other.letters_to_be_counted = VOWELS;

  strcpy (different.buffer, "abcdefghijklmnopqrstuvwxyz");
  different.letters_to_be_counted = "az";

  //  callforward is gently overloaded by the compiler using the template
  //  function declared earlier.
  //
  //  callforw (simple,    "simple"); will fail

  callforw (simple);
  callforw (other);
  callforw (different);
}