[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

3419.0. "Help with template?" by GALVIA::STONES (Tom Stones) Fri Jan 31 1997 11:11

I'm compiling code that uses a template, and I'm getting the following error,
and I'm not too sure what to do about it.  I'm fairly new at c++, so I'm
probably doing something stupid in the code.  I'd be gratefull for a lesson.

Ta,
Tom.

zen> cxx -g -o test test.cpp cache.cpp
test.cpp:
cache.cpp:
cxx: Error: ./cxx_repository/Cache_t__T14EpMcMapEntry_t.cxx, line 3: In this
declaration, the argument "EpMcMapEntry_t" for template parameter CACHE_DATA_T
is an expression where a type is expected, or vice versa.
typedef Cache_t<EpMcMapEntry_t > __dummy_;
----------------^
ld:
Unresolved:
Cache_t<EpMcMapEntry_t>::Added(const EpMcMapEntry_t&)
Cache_t<EpMcMapEntry_t>::Cache_t<EpMcMapEntry_t>(void)
Cache_t<EpMcMapEntry_t>::~Cache_t<EpMcMapEntry_t>(void)



Here's the code:

//test.cpp
#include "cache.h"

typedef void* McRx_t;
typedef void* McTx_t;

class EpMcMapEntry_t {
public:
  long epAddr;
  McRx_t rcsRx;
  McTx_t rcsTx;
  int Matches(const EpMcMapEntry_t &data) {return (epAddr==data.epAddr);}
};

void main() {
  Cache_t<EpMcMapEntry_t> tcc;
  EpMcMapEntry_t data;
  int status;

  for (int i=0;i<10;i++) { 
    data.epAddr = i;
    data.rcsRx = (void*) i;
    data.rcsTx = (void*) i;
    status = tcc.Added(data);
  }
}

//cache.h
#ifndef MCM_CACHE_
#define MCM_CACHE_

//Implements a generic caching mechanism.
//The base class for the cache must have a "Matches" function:
//  int Matches(CACHE_DATA_T &data) - returns 1 iff "data" matches "this"
//
//Implemented as a linked list of data entries.  The entries are allocated
//in blocks, and a free list is maintained.  A list of the blocks is also
//maintained.


template<class CACHE_DATA_T> 
class Cache_t {
  //Implements a cache. as a linked list of cacheblocks.
private:

  //Each entry in the cache is data plus ptr to next.
  
  struct Entry_t {		
    CACHE_DATA_T data;
    Entry_t      *nextEntry;
  };

  //Entries are allocated in blocks.
  struct CbListEntry_t{
    void *cacheblock;
    CbListEntry_t *nextCbListEntry;
  };
  
  Entry_t *firstEntry;
  Entry_t *freeEntry;
  CbListEntry_t  cb;

  //MoreEntries - Allocates space for cache entries and updates freeEntry.
  //Returns 1 if one or more entries added to free list.
  //Returns 0 if no memory.
  static int MoreEntries();
 
public:
  //Add a new entry to the cache.
  //Returns 1 if ok.  0 if not enough memory.  
  int Added(const CACHE_DATA_T &newEntry);

  //Delete an entry from the cache.
  void Delete(const CACHE_DATA_T &selectedEntry);
  
  //Search the cache.
  //Returns 1 and result in selectedEntry if found.
  //Returns 0 if not found.
  int Found(CACHE_DATA_T *selectedEntry);

  //Constructor.
  Cache_t();

  //Destructor.
  ~Cache_t();

};


#endif


//cache.cpp
#include "cache.h"

template<class CACHE_DATA_T> 
static int Cache_t::MoreEntries() {
  const int iMax = 8196/sizeof(Entry_t);   //An 8K page of entries. 
  CbListEntry_t *cble = new CbListEntry_t();
  Entry_t *entry = new Entry_t[iMax];
  
  if ((!entry) || (!cble) ) {
    //Out of memory.
    delete [] entry;
    delete cble;
    return 0;
  }

  //Chain these entries.
  for (int i=0; i<iMax-1; i++) {
    entry[i].nextEntry = &(entry[i+1]);
  }

  //Add the lot to the free list.
  entry[iMax-1].nextEntry = freeEntry;
  freeEntry = &(entry[0]);

  //Add the new cacheblock to the cacheblock list.
  cble->cacheblock = entry;
  cble->nextCbListEntry = cb.nextCbListEntry;

  return 1;
}

template<class CACHE_DATA_T> 
int Cache_t::Added(const CACHE_DATA_T &newEntry) {
  Entry_t *entry;

  //If there's no more free space, allocate some.
  if (!freeEntry) {
    if (!MoreEntries()) {
      //No more memory.
      return 0;
    }
  }

  //Take the 1st entry from the free list.
  entry = freeEntry;
  freeEntry = entry->nextEntry;

  //Fill in the data and add to head of cache list.
  entry->data = newEntry;
  entry->nextEntry = firstEntry;
  firstEntry = entry;

  return 1;
}


template<class CACHE_DATA_T> 
void Cache_t::Delete(const CACHE_DATA_T &selectedData) {
  //Run through the list of cached entries one of them says it matches
  //the selected entry, or we hit the end of the list.
  Entry_t *entry = firstEntry;
  Entry_t **link = &firstEntry;
  while (entry && !entry->data.Matched(selectedData)) {
    entry = entry->nextEntry;
    link  = &entry->nextEntry;
  }

  //If we've hit the end of the list, just return quietly.
  if (!entry) {
    return;
  }

  //Remove the entry from the cache list.
  *link = entry->nextEntry;
  //Add the entry to head of free list.
  entry->nextEntry = freeEntry;
  freeEntry = entry;
}

template<class CACHE_DATA_T> 
int Cache_t::Found(const CACHE_DATA_T *selectedData) {
  //Run through the list of cached entries one of them says it matches
  //the selected entry, or we hit the end of the list.
  Entry_t *entry = firstEntry;
  while (entry && !entry->data.Matched(selectedData)) {
    entry = entry->nextEntry;
  }

  //If we hit the end of the list - it's not found.
  if (!entry) {
    return 0;
  }

  selectedData = entry->data;
  return 1;
}
  
template<class CACHE_DATA_T> 
Cache_t::Cache_t() {
  //Constructor.

  //Initialise all the member data.
  firstEntry = NULL;
  freeEntry = NULL;
  cb.cacheblock = NULL;
  cb.nextCbListEntry = NULL;

  //Allocate the 1st cacheblock.
  MoreEntries();
}

template<class CACHE_DATA_T> 
Cache_t::~Cache_t() {
  //Destructor.  Zap all the cacheblocks.
  CbListEntry_t *cble = cb.nextCbListEntry;
  CbListEntry_t *cbleTmp;
 
  while (cble) {
    delete cble->cacheblock;
    cbleTmp = cble->nextCbListEntry;
    delete cble;
    cble = cbleTmp;
  }
  delete cb.cacheblock;
}
T.RTitleUserPersonal
Name
DateLines
3419.1SPECXN::DERAMODan D&#039;EramoFri Jan 31 1997 11:2317
	It looks like you are violating a contraint on using automatic
        template instantiation.
        
        Your ``template<class CACHE_DATA_T> class Cache_t'' is
        correctly broken up into interface in "cache.h" and
        implementation in "cache.cpp".
        
        But to use Cache_t<EpMcMapEntry_t> with auotmatic template
        instantiation the class EpMcMapEntry_t must also be provided
        in a header file included by test.cpp instead of being defined
        directly inside test.cpp.
        
        If you move the declaration of EpMcMapEntry_t into its own
        header file, protected by the usual double-inclusion guards,
        then you should get past this particular problem.
        
        Dan
3419.2Thanks.GALVIA::STONESTom StonesMon Feb 03 1997 04:181
...interesting error message though!
3419.3SPECXN::DERAMODan D&#039;EramoMon Feb 03 1997 11:1442
>.2
>...interesting error message though!
        
>.0
>zen> cxx -g -o test test.cpp cache.cpp
>test.cpp:
>cache.cpp:
>cxx: Error: ./cxx_repository/Cache_t__T14EpMcMapEntry_t.cxx, line 3: In this
>declaration, the argument "EpMcMapEntry_t" for template parameter CACHE_DATA_T
>is an expression where a type is expected, or vice versa.
>typedef Cache_t<EpMcMapEntry_t > __dummy_;
>----------------^
>ld:
>Unresolved:
>Cache_t<EpMcMapEntry_t>::Added(const EpMcMapEntry_t&)
>Cache_t<EpMcMapEntry_t>::Cache_t<EpMcMapEntry_t>(void)
>Cache_t<EpMcMapEntry_t>::~Cache_t<EpMcMapEntry_t>(void)
        
        The source file in the message
        
        	./cxx_repository/Cache_t__T14EpMcMapEntry_t.cxx
        
        would be one of the compiler-generated files for automatic
        template instantiation.  It uses Cache_t<EpMcMapEntry_t> as
        shown by the error message, but none of the header files it
        picked up from test.cpp defined EpMcMapEntry_t.  Since
        EpMcMapEntry_t was not declared as a type, the compiler
        probably took it as a variable (also undeclared), which would
        make it an expression where a type was expected.
        
        I suppose "EpMcMapEntry_t is not declared" or "cannot
        instantiate template Cache_t with undeclared EpMcMapEntry_t"
        would be better diagnostic messages.
        
        Then the ld errors would result from not being able to
        instantiate Cache_t<EpMcMapEntry_t>.
        
        When you read the generated file
        ./cxx_repository/Cache_t__T14EpMcMapEntry_t.cxx then you can
        see why the approach in .1 is necessary.
        
        Dan