很多的奇怪错误,如
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.
*/
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.
*/
head.next=head.next->previous=pchunk;
}
else{ /* link the cell to the list of available cells for this chunk */
pchunk->pfirst_available_cell=pcell;
}
} /* standard stuff */ void construct(pointer p,const T& val)
{
new ((void *)p) T(val);
} void destroy(pointer p)
{
p->T::~T();
} size_type max_size()const
{
size_type n=(size_type)(-1)/sizeof(N);
return (0<n?n:1);
} /* This four member functions never get called, but VC complains if no
* declaration for them is provided. See documentation for this
* VC++ confirmed bug in the Microsoft Knowledge Base, article Q166721.
* I think this has been fixed in VC++ 6.0.
*/
// PGS - Evidently, under the current version of VC++, operator== does get called.
// The function body is a quick fix - not necessarily appropriate for all uses. bool operator <(const block_allocator<T,N,chunk_size> &) const;
bool operator >(const block_allocator<T,N,chunk_size> &) const;
bool operator ==(const block_allocator<T,N,chunk_size> &) const {return true;}
bool operator !=(const block_allocator<T,N,chunk_size> &) const; private:
/* some typing saving typedefs */ typedef block_allocator_cell<sizeof(N),chunk_size> cell;
typedef block_allocator_chunk_header<sizeof(N),chunk_size> chunk_header;
typedef block_allocator_chunk<sizeof(N),chunk_size> chunk; /* dummy elements at the beginning and end of the list of available
* chunks. We could have done whithout these, but they allow for a
* slightly more efficient code.
*/ chunk_header head;
chunk_header tail;
};/* We keep the following definitions out of the multiple include preventing
* #endif, so that different include's can be used to define different
* block allocated containers, as in this example:
*
* #define DEFINE_BLOCK_ALLOCATED_LIST
* #include "blockallocator.h"
*
* #define DEFINE_BLOCK_ALLOCATED_MULTIMAP
* #include "blockallocator.h"
*
*/#elif VERSION_BLOCKALLOCATOR!=0x00010001
#error You have included two BLOCKALLOCATOR.H with different version numbers
#endif/* Definitions for each container supported. These need the corresponding
* STL headers to be included, so they come with associated macros
* to turn them on only in the case you really want them.
* Each definition comes with a helper struct named MSVC_STL_XXX_node.
* This struct mimics the layout of the objects for which the container
* will request memory to our allocator, so they are used to calculate the
* size of the nodes required.
*/#ifdef DEFINE_BLOCK_ALLOCATED_LIST
#ifndef BLOCK_ALLOCATED_LIST_DEFINED
#define BLOCK_ALLOCATED_LIST_DEFINED#pragma warning(disable:4786)
#include<list>#pragma pack(push,8)template <class T> struct MSVC_STL_list_node
{
void *p1,*p2;
T t;
};#pragma pack(pop)template <class T,size_t chunk_size>
class block_allocated_list:
public std::list<T,block_allocator<T,MSVC_STL_list_node<T>,chunk_size> >
{
public:
explicit block_allocated_list(
const allocator_type& al=block_allocator<T,MSVC_STL_list_node<T>,chunk_size>()
):
std::list<T,block_allocator<T,MSVC_STL_list_node<T>,chunk_size> >(al)
{
} explicit block_allocated_list(
size_type n,const T& v=T(),
const allocator_type& al=block_allocator<T,MSVC_STL_list_node<T>,chunk_size>()
):
std::list<T,block_allocator<T,MSVC_STL_list_node<T>,chunk_size> >(n,v,al)
{
} block_allocated_list(
const_iterator first,const_iterator last,
const allocator_type& al=block_allocator<T,MSVC_STL_list_node<T>,chunk_size>()
):
std::list<T,block_allocator<T,MSVC_STL_list_node<T>,chunk_size> >(first,last,al)
{
}
};#endif
#endif /* DEFINE_BLOCK_ALLOCATED_LIST */#ifdef DEFINE_BLOCK_ALLOCATED_SET
#ifndef BLOCK_ALLOCATED_SET_DEFINED
#define BLOCK_ALLOCATED_SET_DEFINED#pragma warning(disable:4786)
#include<set>#pragma pack(push,8)template <class T> struct MSVC_STL_set_node
{
void *p1,*p2,*p3;
T t;
int i;
};#pragma pack(pop)template <class Key,size_t chunk_size,class Pred=std::less<Key> >
class block_allocated_set:
public std::set<Key,Pred,
block_allocator<Key,MSVC_STL_set_node<Key>,chunk_size> >
{
public:
explicit block_allocated_set(
const Pred& comp=Pred(),
const allocator_type& al=block_allocator<Key,MSVC_STL_set_node<Key>,chunk_size>()
):
std::set<Key,Pred,block_allocator<Key,MSVC_STL_set_node<Key>,chunk_size> >(comp,al)
{
} block_allocated_set(
const value_type *first,const value_type *last,const Pred& comp=Pred(),
const allocator_type& al=block_allocator<Key,MSVC_STL_set_node<Key>,chunk_size>()
):
std::set<Key,Pred,block_allocator<Key,MSVC_STL_set_node<Key>,chunk_size> >
(first,last,comp,al)
{
}
};#endif
#endif /* DEFINE_BLOCK_ALLOCATED_SET */#ifdef DEFINE_BLOCK_ALLOCATED_MULTISET
#ifndef BLOCK_ALLOCATED_MULTISET_DEFINED
#define BLOCK_ALLOCATED_MULTISET_DEFINED#pragma warning(disable:4786)
#include<set>#pragma pack(push,8)template <class T> struct MSVC_STL_multiset_node
{
void *p1,*p2,*p3;
T t;
int i;
};
class block_allocated_multiset:
public std::multiset<Key,Pred,
block_allocator<Key,MSVC_STL_multiset_node<Key>,chunk_size> >
{
public:
explicit block_allocated_multiset(
const Pred& comp=Pred(),
const allocator_type& al=block_allocator<Key,MSVC_STL_multiset_node<Key>,chunk_size>()
):
std::multiset<Key,Pred,block_allocator<Key,MSVC_STL_multiset_node<Key>,chunk_size> >
(comp,al)
{
} block_allocated_multiset(
const value_type *first,const value_type *last,const Pred& comp=Pred(),
const allocator_type& al=block_allocator<Key,MSVC_STL_multiset_node<Key>,chunk_size>()
):
std::multiset<Key,Pred,block_allocator<Key,MSVC_STL_multiset_node<Key>,chunk_size> >
(first,last,comp,al)
{
}
};#endif
#endif /* DEFINE_BLOCK_ALLOCATED_MULTISET */#ifdef DEFINE_BLOCK_ALLOCATED_MAP
#ifndef BLOCK_ALLOCATED_MAP_DEFINED
#define BLOCK_ALLOCATED_MAP_DEFINED#pragma warning(disable:4786)
#include<map>#pragma pack(push,8)template <class Key,class T> struct MSVC_STL_map_node
{
void *p1,*p2,*p3;
std::pair<Key,T> t;
int i;
};#pragma pack(pop)template<class Key,class T,size_t chunk_size,class Pred=std::less<Key> >
class block_allocated_map:
public std::map<Key,T,Pred,
block_allocator<T,MSVC_STL_map_node<Key,T>,chunk_size> >
{
public:
explicit block_allocated_map(
const Pred& comp=Pred(),
const allocator_type& al=block_allocator<T,MSVC_STL_map_node<Key,T>,chunk_size>()
):
std::map<Key,T,Pred,block_allocator<T,MSVC_STL_map_node<Key,T>,chunk_size> >(comp,al)
{
} block_allocated_map(
const value_type *first,const value_type *last,const Pred& comp=Pred(),
const allocator_type& al=block_allocator<T,MSVC_STL_map_node<Key,T>,chunk_size>()
):
std::map<Key,T,Pred,block_allocator<T,MSVC_STL_map_node<Key,T>,chunk_size> >
(first,last,comp,al)
{
}
};#endif
#endif /* DEFINE_BLOCK_ALLOCATED_MAP */#ifdef DEFINE_BLOCK_ALLOCATED_MULTIMAP
#ifndef BLOCK_ALLOCATED_MULTIMAP_DEFINED
#define BLOCK_ALLOCATED_MULTIMAP_DEFINED#pragma warning(disable:4786)
#include<map>#pragma pack(push,8)template <class Key,class T> struct MSVC_STL_multimap_node
{
void *p1,*p2,*p3;
std::pair<Key,T> t;
int i;
};#pragma pack(pop)template<class Key,class T,size_t chunk_size,class Pred=std::less<Key> >
class block_allocated_multimap:
public std::multimap<Key,T,Pred,
block_allocator<T,MSVC_STL_multimap_node<Key,T>,chunk_size> >
{
public:
explicit block_allocated_multimap(
const Pred& comp=Pred(),
const allocator_type& al=block_allocator<T,MSVC_STL_multimap_node<Key,T>,chunk_size>()
):
std::multimap<Key,T,Pred,block_allocator<T,MSVC_STL_multimap_node<Key,T>,chunk_size> >
(comp,al)
{
} block_allocated_multimap(
const value_type *first,const value_type *last,const Pred& comp=Pred(),
const allocator_type& al=block_allocator<T,MSVC_STL_multimap_node<Key,T>,chunk_size>()
):
std::multimap<Key,T,Pred,block_allocator<T,MSVC_STL_multimap_node<Key,T>,chunk_size> >
(first,last,comp,al)
{
}
};#endif
#endif /* DEFINE_BLOCK_ALLOCATED_MULTIMAP */
后加个using namespace std;看看
vc6与vc2003对于标准的支持不一样,vc2003要更好
加过了,没用to oyljerry(【勇敢的心】→ ㊣Looking ahead√㊣)
我就是怀疑这个程序里面用了什么不是标准的特性,所以vc2003编译不通过
并将链接库Libci.lib、Libcimt.lib、Msvcirt.lib
改为:Libcp.lib、Libcpmt.lib、Msvcprt.lib
试
不是库的问题,因为是编译错误
另外,都是用的新的头文件,关键是出错得很奇怪,提示在<list>里出错