[Search for users]
[Overall Top Noters]
[List of all Conferences]
[Download this site]
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.R | Title | User | Personal Name | Date | Lines |
---|
3419.1 | | SPECXN::DERAMO | Dan D'Eramo | Fri Jan 31 1997 11:23 | 17 |
| 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.2 | Thanks. | GALVIA::STONES | Tom Stones | Mon Feb 03 1997 04:18 | 1 |
| ...interesting error message though!
|
3419.3 | | SPECXN::DERAMO | Dan D'Eramo | Mon Feb 03 1997 11:14 | 42 |
| >.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
|