template奇怪问题,vc6可以通过,vc2003编译错误!
很多的奇怪错误,如
e:\Visual Studio 2003\Vc7\include\list(28): error C2903: 'rebind' : symbol is neither a class template nor a function template
下面是原代码,比较长,是个头文件,高手可以直接copy下去编译一下看,谢谢!
使用的时候要先在cpp里加上
#define DEFINE_BLOCK_ALLOCATED_LIST
#include "blockallocator.h"
太长了,所以分几部分发
#ifndef BLOCKALLOCATOR_H
#define BLOCKALLOCATOR_H
#define VERSION_BLOCKALLOCATOR 0x00010001
#include <stddef.h>
#include <assert.h>
/* forward declaration */
template <size_t node_size,size_t chunk_size> struct block_allocator_chunk;
/* A cell has information on the chunk it belongs in and a pointer
* for keeping a linked list of free cells. To save space, next and
* node have been merged into a union (next is only used when the
* cell is not used by the caller).
*/
template <size_t node_size,size_t chunk_size> struct block_allocator_cell
{
block_allocator_chunk<node_size,chunk_size> *pchunk;
union{
block_allocator_cell<node_size,chunk_size> *next;
char node[node_size];
};
};
/* A chunk has pointers to other chunks to keep a double linked
* list of non-full chunks, as well as a pointer to its first
* available cell.
*/
/* Define block_allocator_chunk_header separately so that we
* can place dummy elements at the beginning and end of the linked list
* whitout the overhead of the data.
*/
template <size_t node_size,size_t chunk_size> struct block_allocator_chunk_header
{
block_allocator_chunk<node_size,chunk_size> *previous;
block_allocator_chunk<node_size,chunk_size> *next;
block_allocator_chunk_header(block_allocator_chunk<node_size,chunk_size> *previous=0,
block_allocator_chunk<node_size,chunk_size> *next=0):
previous(previous),
next(next)
{
}
};
template <size_t node_size,size_t chunk_size> struct block_allocator_chunk:
public block_allocator_chunk_header<node_size,chunk_size>
{
size_t num_used_cells;
block_allocator_cell<node_size,chunk_size> *pfirst_available_cell;
/* workaround for MSVC++ 6.0 bug. See "Modifications to v1.0" paragraph */
enum{_chunk_size=chunk_size};
block_allocator_cell<node_size,_chunk_size> cells[chunk_size];
/* The ctor puts the object in a state in which the first
* cell is already "allocated". This saves some instructions
* in the code.
*/
block_allocator_chunk(block_allocator_chunk<node_size,chunk_size> *previous,
block_allocator_chunk<node_size,chunk_size> *next):
block_allocator_chunk_header<node_size,chunk_size>(previous,next),
num_used_cells(1),
pfirst_available_cell(&cells[1])
{
/* link it */
previous->next=next->previous=this;
/* initialize cells */
cells[0].pchunk=this;
cells[chunk_size-1].pchunk=this;
cells[chunk_size-1].next=0;
block_allocator_cell<node_size,chunk_size> *pcell=&cells[1];
block_allocator_cell<node_size,chunk_size> *pnext_cell=&cells[2];
for(size_t n=chunk_size-2;n--;){
pcell->pchunk=this;
pcell++->next=pnext_cell++;
}
}
};
/* The template arguments of block_allocator are:
* ?T, the type of the elements contained.
* ?N, a class whose sizeof() determines the number of bytes
* the allocator will be requested in every call to _Charalloc(),
* ?chunk_size, the number of nodes per chunk.
*/
template <class T,class N,size_t chunk_size> class block_allocator
{
public:
/* Standard definitions, borrowed from the default VC++ allocator */
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T *pointer;
typedef const T *const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
pointer address(reference x)const{return &x;}
const_pointer address(const_reference x)const{return &x;}
block_allocator()
{
head.next=reinterpret_cast<chunk *>(&tail);
tail.previous=reinterpret_cast<chunk *>(&head);
/* The code assumes chunk_size>=2. If that's not the case, it
* will crash for sure.
*/
assert(chunk_size>=2);
}
block_allocator(const block_allocator&)
{
/* same as default ctor */
head.next=reinterpret_cast<chunk *>(&tail);
tail.previous=reinterpret_cast<chunk *>(&head);
assert(chunk_size>=2);
}
/* see MSVC++ docs on this member funtion */
block_allocator<T,N,chunk_size>& operator=(const block_allocator<T,N,chunk_size>)
{
return *this;
}
/* containers supported never call this one */
pointer allocate(size_type n,const void *hint)
{
assert(false);
return 0;
}
char *_Charalloc(size_type n)
{
assert(n==sizeof(N));
cell *pcell;
if(head.next==&tail){ /* no chunks available */
new chunk(reinterpret_cast<chunk *>(&head), /* get a new one */
reinterpret_cast<chunk *>(&tail));
pcell=&head.next->cells[0]; /* use its first cell */
}
else{
pcell=head.next->pfirst_available_cell; /* get the cell */
++head.next->num_used_cells; /* and log it */
if((head.next->pfirst_available_cell=pcell->next)==0){
/* no more cells available in this chunk, delink it */
head.next=head.next->next;
head.next->previous=reinterpret_cast<chunk *>(&head);
}
}
/* return the node portion of the cell */
return reinterpret_cast<char *>(&pcell->node);
}
void deallocate(void *p,size_type n)
{
assert(p!=0&&n==1);
cell *pcell=reinterpret_cast<cell *>(reinterpret_cast<char *>(p)-offsetof(cell,node));
chunk *pchunk=pcell->pchunk;
if(--pchunk->num_used_cells==0){
/* all cells in this chunk disposed of, delete and delink */
pchunk->previous->next=pchunk->next;
pchunk->next->previous=pchunk->previous;
delete pchunk;
}
else if((pcell->next=pchunk->pfirst_available_cell)==0){
pchunk->pfirst_available_cell=pcell;
/* all cells in this chunk were in use and this is the first
* that gets deallocated, link the chunk at the beginning of
* the list.
* NB: We don't need set pchunk->previous: it already pointed
* to head when the chunk got delinked.
*/