stl set 实现traits是怎样实现的

特化;2、萃取拿相同的代码提取不同的类型;3、整个搭建框架如下:650) this.width=," />
STL的框架实现
责任编辑:词汇网 发表时间: 9:46:40
1、模板的特化&&&&泛化模板 : 对各种不同版本的特殊化处理---->特化;2、萃取&&&&拿相同的代码提取不同的类型;3、整个搭建框架如下:650) this.width=650;" src="/wyfs02/M00/86/91/wKioL1fECo-h02dwAAA-SBIjtIU626.png-wh_500x0-wm_3-wmp_4-s_.png" title="QQ截图19.png" alt="wKioL1fECo-h02dwAAA-SBIjtIU626.png-wh_50" />&&&&在这里已经不关心空间配置器是如何实现的;&&& 其框架代码如下:#ifndef&_MEMORY_H_#define&_MEMORY_H_#include"stl_alloc.h"#include"stl_iterator.h"#include"type_traits.h"#include"stl_construct.h"#include"stl_uninitialized.h"#endif////////////////////////////////////////////////////////////////////////////////////#if&1#include#include#includeusing&namespace&//#define&__THROW_BAD_ALLOC&&&throw&&&bad_alloc#define&__THROW_BAD_ALLOC&&cerr<<"Throw&bad&alloc,&Out&Of&Memory."<<&exit(1)#elif&&!defined&&(__THROW_BAD_ALLOC)#include#define&__THROW_BAD_ALLOC&&&cerr<<"out&of&memory"<<&exit(1);#endiftemplateclass&__malloc_alloc_template{private:&&&&static&void*&oom_malloc(size_t);&&&&static&void*&oom_realloc(void&*,&size_t);&&&&static&void(*&__malloc_alloc_oom_handler)();public:&&&&static&void*&allocate(size_t&n){&&&&&&&&void&*result&=&malloc(n);&&&&&&&&if(0&==&result){&&&&&&&&&&&&result&=&oom_malloc(n);&&&&&&&&}&&&&&&&&return&&&&&}&&&&static&void&&&deallocate(void&*p,&size_t){&&&&&&&&free(p);&&&&}&&&&static&void*&reallocate(void&*p,&size_t,&size_t&new_sz){&&&&&&&&void&*result&=&realloc(p,&new_sz);&&&&&&&&if(0&==&result){&&&&&&&&&&&&oom_realloc(p,new_sz);&&&&&&&&}&&&&&&&&return&&&&&}public:&&&&//set_new_handler(Out_Of_Memory);&&&&static&void(*set_malloc_handler(void(*f)()))(){&&&&&&&&void(*old)()&=&__malloc_alloc_oom_&&&&&&&&__malloc_alloc_oom_handler&=&f;&&&&&&&&return&&&&&}};templatevoid&(*__malloc_alloc_template::__malloc_alloc_oom_handler)()&=&0;templatevoid*&__malloc_alloc_template::oom_malloc(size_t&n){&&&&void&*&&&&void(*&my_malloc_handler)();&&&&for(;;){&&&&&&&&my_malloc_handler&=&__malloc_alloc_oom_&&&&&&&&if(0&==&my_malloc_handler){&&&&&&&&&&&&&__THROW_BAD_ALLOC;&&&&&&&&}&&&&&&&&(*my_malloc_handler)();&&&&&&&&result&=&malloc(n);&&&&&&&&if(result){&&&&&&&&&&&&return&&&&&&&&&}&&&&}}templatevoid*&__malloc_alloc_template::oom_realloc(void&*p,&size_t&n){&&&&void(*my_malloc_handler)();&&&&void&*&&&&for(;;){&&&&&&&&my_malloc_handler&=&__malloc_alloc_oom_&&&&&&&&if(0&==&my_malloc_handler){&&&&&&&&&&&&__THROW_BAD_ALLOC;&&&&&&&&}&&&&&&&&(*my_malloc_handler)();&&&&&&&&result&=&realloc(p,&n);&&&&&&&&if(result){&&&&&&&&&&&&return&&&&&&&&&}&&&&}}typedef&__malloc_alloc_template&malloc_/////////////////////////////////////////////////////////////////////////////////////enum&{__ALIGN&=&8};enum&{__MAX_BYTES&&=&128};enum&{__NFREELISTS&=&__MAX_BYTES&/&__ALIGN};templateclass&__default_alloc_template{public:&&&&static&void*&allocate(size_t&n);&&&&static&void&&deallocate(void&*p,&size_t&n);&&&&static&void*&reallocate(void&*p,&size_t,&size_t&new_sz);private:&&&&static&size_t&&ROUND_UP(size_t&bytes){&&&&&&&&return&(((bytes)&+&__ALIGN-1)&&&~(__ALIGN-1));&&&&}private:&&&&union&obj{&&&&&&&&union&obj&*&free_list_&&&&&&&&char&client_data[1];&&&&};private:&&&&static&obj*&volatile&free_list[__NFREELISTS];&&&&static&size_t&FREELIST_INDEX(size_t&bytes){&&&&&&&&return&((bytes)+__ALIGN-1)&/&__ALIGN-1;&&&&}private:&&&&static&char&*start_&&&&static&char&*end_&&&&static&size_t&heap_&&&&static&void&*refill(size_t&n);&&&&static&char*&chunk_alloc(size_t&size,&int&&nobjs);};templatechar*&__default_alloc_template::start_free&=&0;templatechar*&__default_alloc_template::end_free&=&0;templatesize_t&__default_alloc_template::heap_size&=&0;templatetypename&__default_alloc_template::obj*&volatile__default_alloc_template::free_list[__NFREELISTS]&=&{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};templatevoid*&__default_alloc_template::allocate(size_t&n){&&&&obj&*&volatile&*my_free_&&&&obj&*&&&&if(n&>&__MAX_BYTES){&&&&&&&&return&malloc_alloc::allocate(n);&&&&}&&&&my_free_list&=&free_list&+&FREELIST_INDEX(n);&&&&result&=&*my_free_&&&&if(result&==&0){&&&&&&&&void&*r&=&refill(ROUND_UP(n));&&&&&&&&return&r;&&&&}&&&&*my_free_list&=&result->free_list_&&&&return&&}templatevoid*&__default_alloc_template::refill(size_t&n){&&&&int&nobjs&=&20;&&&&char&*chunk&=&chunk_alloc(n,&nobjs);&&&&obj&*&volatile&*my_free_&&&&obj&*&&&&obj&*current_obj,&*next_&&&&int&i;&&&&if(1&==&nobjs){&&&&&&&&return&&&&&}&&&&my_free_list&=&free_list&+&FREELIST_INDEX(n);&&&&result&=&(obj*)&&&&*my_free_list&=&next_obj&=&(obj*)(chunk+n);&&&&for(i=1;&;&++i){&&&&&&&&current_obj&=&next_&&&&&&&&next_obj&=&(obj*)((char*)next_obj+n);&&&&&&&&if(nobjs&-&1&==&i){&&&&&&&&&&&&current_obj->free_list_link&=&0;&&&&&&&&&&&&&&&&&&&&}else{&&&&&&&&&&&&current_obj->free_list_link&=&next_&&&&&&&&}&&&&}&&&&return&}templatechar*&__default_alloc_template::chunk_alloc(size_t&size,&int&&nobjs){&&&&char&*&&&&size_t&total_bytes&=&size&*&&&&&size_t&bytes_left&=&end_free&-&start_&&&&if(bytes_left&>=&total_bytes){&&&&&&&&result&=&start_&&&&&&&&start_free&+=&total_&&&&&&&&return&&&&&}&&&&else&if(bytes_left&>=&size){&&&&&&&&nobjs&=&bytes_left&/&&&&&&&&&total_bytes&=&size&*&&&&&&&&&result&=&start_&&&&&&&&start_free&+=&total_&&&&&&&&return&&&&&}else{&&&&&&&&size_t&bytes_to_get&=&2&*&total_bytes&+&ROUND_UP(heap_size&>>&4);&&&&&&&&if(bytes_left&>&0){&&&&&&&&&&&&obj&*&volatile&*&my_free_list&=&free_list&+&FREELIST_INDEX(bytes_left);&&&&&&&&&&&&((obj*)start_free)->free_list_link&=&*my_free_&&&&&&&&&&&&*my_free_list&=&(obj&*)start_&&&&&&&&}&&&&&&&&start_free&=&(char&*)malloc(bytes_to_get);&&&&&&&&if(0&==&start_free){&&&&&&&&&&&&int&i;&&&&&&&&&&&&obj&*&volatile&*my_free_list,&*p;&&&&&&&&&&&&for(i=&ifree_list_&&&&&&&&&&&&&&&&&&&&start_free&=&(char&*)p;&&&&&&&&&&&&&&&&&&&&end_free&=&start_free&+&i;&&&&&&&&&&&&&&&&&&&&return&chunk_alloc(size,&nobjs);&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&&&&&end_free&=&0;&&&&&&&&&&&&start_free&=&(char&*)malloc_alloc::allocate(bytes_to_get);&&&&&&&&}&&&&&&&&heap_size&&+=&bytes_to_&&&&&&&&end_free&=&start_free&+&bytes_to_&&&&&&&&return&chunk_alloc(size,&nobjs);&&&&}}/////////////////////////////////////////////////////////////////////////////////#ifdef&__USE_MALLOCtypedef&malloc_alloc&&#elsetypedef&__default_alloc_template&#endiftemplateclass&simple_alloc{&public:&&&&static&T*&allocate(size_t&n){&&&&&&&&return&0==n&?&0&:&(T*)Alloc::allocate(n&*&sizeof(T));&&&&}&&&&static&T*&allocate(void){&&&&&&&&return&(T*)Alloc::allocate(sizeof(T));&&&&}&&&&static&void&deallocate(T&*p,&size_t&n){&&&&&&&&if(0!=n)&Alloc::deallocate(p,&n*sizeof(T));&&&&}&&&&static&void&deallocate(T&*p){&&&&&&&&Alloc::deallocate(p,sizeof(T));&&&&}};//////////////////////////////////////////////////////////////////////////////////////////#ifndef&__STL_CONFIG_H#define&__STL_CONFIG_H//#define&__USE_MALLOC#endif//////////////////////////////////////////////////////////////////////////////////////////#ifndef&__STL_CONSTRUCT_H#define&__STL_CONSTRUCT_Htemplate&void&construct(T1*&p,&const&T2&&value){&&&&&&new&(p)&T1(value);}#endif////////////////////////////////////////////////////////////////////////////////////////#ifndef&__STL_ITERATOR_H#define&__STL_ITERATOR_Htemplate&T*&value_type(const&T*){&&&&return&(T*)(0);&}#endif////////////////////////////////////////////////////////////////////////////////////////#ifndef&__STL_UNINITIALIZED_H#define&__STL_UNINITIALIZED_HtemplateForwardIterator&_uninitialized_fill_n_aux(ForwardIterator&first,&Size&n,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&T&&x,&_true_type){&&&&cout<<"yyyyyyyyyyy"<<&&&&return&fill_n(first,&n,&x);}templateForwardIterator&_uninitialized_fill_n_aux(ForwardIterator&first,&Size&n,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&T&&x,&_false_type){&&&&ForwardIterator&cur&=&&&&&for(;&n>0;&--n,&++cur){&&&&&&&&cout<<"xxxxxxxxxxxx"<<&&&&&&&&construct(&&*cur,&x);&//construct(cur,&x);&&&&}&&&&return&}templateForwardIterator&_uninitialized_fill_n(ForwardIterator&first,&Size&n,&const&T&&x,&&T1*){&&&&//typedef&_false_type&&is_POD;&&&&typedef&typename&_type_traits::is_POD_type&&&is_POD;&&&&//return&_uninitialized_fill_n(first,&n,&x,&_false_type());&&&&return&_uninitialized_fill_n_aux(first,&n,&x,&is_POD());}templateForwardIterator&uninitialized_fill_n(ForwardIterator&first,&Size&n,&const&T&&x){&&&&return&_uninitialized_fill_n(first,&n,&x,&value_type(first));}#endif////////////////////////////////////////////////////////////////////////////////////////#ifndef&__STL_VECTOR_H#define&__STL_VECTOR_Htemplateclass&vector{public:&&&&typedef&T&&&&&&&&&&&value_&&&&typedef&value_type*&&&&&typedef&value_type*&&&&&typedef&value_type&&&&&&typedef&size_t&&&&&&size_&&&&typedef&ptrdiff_t&&&difference_public:&&&&vector()&:&start(0),&finish(0),&end_of_storage(0){}&&&&vector(size_type&n){&&&&&&&&fill_initialize(n,&T());&&&&}protected:&&&&void&fill_initialize(size_type&n,&const&T&&value){&&&&&&&&start&=&allocate_and_fill(n,&value);&&&&&&&&finish&=&start&+&n;&&&&&&&&end_of_storage&=&&&&&}&&&&iterator&allocate_and_fill(size_type&n,&const&T&&x){&&&&&&&&iterator&result&=&data_allocator::allocate(n);&&&&&&&&uninitialized_fill_n(result,&n,&x);&&&&&&&&return&&&&&}protected:&&&&typedef&simple_alloc&data_&&&&iterator&&&&&iterator&&&&&iterator&end_of_};#endif////////////////////////////////////////////////////////////////////////////////////////#ifndef&__TYPE_TRAITS_H#define&__TYPE_TRAITS_H//struct&_true_type&{};struct&_false_type{};template&struct&_type_traits&{&&&&&typedef&_true_type&&&&&this_dummy_member_must_be_&&&&typedef&_false_type&&&&has_trivial_default_&&&&typedef&_false_type&&&&has_trivial_copy_&&&&typedef&_false_type&&&&has_trivial_assignment_&&&&typedef&_false_type&&&&has_trivial_&&&&typedef&_false_type&&&&is_POD_};templatestruct&_type_traits&{&&&&typedef&_true_type&&&&has_trivial_default_&&&&typedef&_true_type&&&&has_trivial_copy_&&&&typedef&_true_type&&&&has_trivial_assignment_&&&&typedef&_true_type&&&&has_trivial_&&&&typedef&_true_type&&&&is_POD_};#endif///////////////////////////////////////////////////////////////////////////////////////#ifndef&_VECTOR_H_#define&_VECTOR_H_#include"memory.h"#include"stl_vector.h"#endif///////////////////////////////////////////////////////////////////////////////////////测试代码#include#include#include"vector.h"using&namespace&class&Test{};int&main(){&&&&vector&v(10);&&//开辟了10个元素的空间;&&&&return&0;测试结果650) this.width=650;" src="/wyfs02/M01/86/92/wKioL1fEDH2yZmnqAABKhjVMTsA557.png-wh_500x0-wm_3-wmp_4-s_.png" title="QQ截图28.png" alt="wKioL1fEDH2yZmnqAABKhjVMTsA557.png-wh_50" />4、分析&&&&(1)、vector的空间灵活性更高;&&&&(2)、POD:也就是标量型别,也就是传统的型别,采取最保险安全的做法,调用构造函数;否则的话,就是调用系统的,基本类型就是&&&&(3)、空构造了2个类型,针对不同萃取得到其_false_type或_true_ 就可以调用不同的函数,进行空间的分配,存在效率上的差异!!!&&&&_true_type:将调用系统的填充函数,效率比较高.&&&&(4)、容器、算法单独好实现,关键是通用性,模板是一种很好的解决方案,真正关键之处还在 : 迭代器的实现;&&&&(5)、空间配置器负责分配、回收空间,只有一个;迭代器针对不同的容器有不同的实现方法!!!词汇网声明本文技术文章来自:51cto
上一集:没有了 下一集:
相关文章:&&
最新添加资讯
24小时热门资讯
附近好友搜索c++ - What is the point of STL Character Traits? - Stack Overflow
to customize your list.
Join the Stack Overflow Community
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.
J it only takes a minute:
I notice that in my copy of the SGI STL reference, there is a page about Character Traits but I can't see how these are used? Do they replace the string.h functions? They don't seem to be used by std::string, e.g. the length() method on std::string doesn't make use of the Character Traits length() method. Why do Character Traits exist and are they ever used in practice?
27.9k113978
2,69542529
Character traits are an extremely important component of the streams and strings libraries because they allow the stream/string classes to separate out the logic of what characters are being stored from the logic of what manipulations should be performed on those characters.
To begin with, the default character traits class, char_traits&T&, is used extensively in the C++ standard.
For example, there is no class called std::string.
Rather, there's a class template std::basic_string that looks like this:
template &typename charT, typename traits = char_traits&charT& &
class basic_
Then, std::string is defined as
typedef basic_string&char&
Similarly, the standard streams are defined as
template &typename charT, typename traits = char_traits&charT& &
class basic_
typedef basic_istream&char&
So why are these classes structured as they are?
Why should we be using a weird traits class as a template argument?
The reason is that in some cases we might want to have a string just like std::string, but with some slightly different properties.
One classic example of this is if you want to store strings in a way that ignores case.
For example, I might want to make a string called CaseInsensitiveString such that I can have
CaseInsensitiveString c1 = "HI!", c2 = "hi!";
if (c1 == c2) {
// Always true
cout && "Strings are equal." &&
That is, I can have a string where two strings differing only in their case sensitivity are compared equal.
Now, suppose that the standard library authors designed strings without using traits.
This would mean that I'd have in the standard library an immensely powerful string class that was entirely useless in my situation.
I couldn't reuse much of the code for this string class, since comparisons would always work against how I wanted them to work.
But by using traits, it's actually possible to reuse the code that drives std::string to get a case-insensitive string.
If you pull up a copy of the C++ ISO standard and look at the definition of how the string's comparison operators work, you'll see that they're all defined in terms of the compare function.
This function is in turn defined by calling
traits::compare(this-&data(), str.data(), rlen)
where str is the string you're comparing to and rlen is the smaller of the two string lengths.
This is actually quite interesting, because it means that the definition of compare directly uses the compare function exported by the traits type specified as a template parameter!
Consequently, if we define a new traits class, then define compare so that it compares characters case-insensitively, we can build a string class that behaves just like std::string, but treats things case-insensitively!
Here's an example.
We inherit from std::char_traits&char& to get the default behavior for all the functions we don't write:
class CaseInsensitiveTraits: public std::char_traits&char& {
static bool lt (char one, char two) {
return std::tolower(one) & std::tolower(two);
static bool eq (char one, char two) {
return std::tolower(one) == std::tolower(two);
static int compare (const char* one, const char* two, size_t length) {
for (size_t i = 0; i & ++i) {
if (lt(one[i], two[i])) return -1;
if (lt(two[i], one[i])) return +1;
(Notice I've also defined eq and lt here, which compare characters for equality and less-than, respectively, and then defined compare in terms of this function).
Now that we have this traits class, we can define CaseInsensitiveString trivially as
typedef std::basic_string&char, CaseInsensitiveTraits& CaseInsensitiveS
And voila!
We now have a string that treats everything case-insensitively!
Of course, there are other reasons besides this for using traits.
For example, if you want to define a string that uses some underlying character type of a fixed-size, then you can specialize char_traits on that type and then make strings from that type.
In the Windows API, for example, there's a type TCHAR that is either a narrow or wide character depending on what macros you set during preprocessing.
You can then make strings out of TCHARs by writing
typedef basic_string&TCHAR&
And now you have a string of TCHARs.
In all of these examples, notice that we just defined some traits class (or used one that already existed) as a parameter to some template type in order to get a string for that type.
The whole point of this is that the basic_string author just needs to specify how to use the traits and we magically can make them use our traits rather than the default to get strings that have some nuance or quirk not part of the default string type.
Hope this helps!
EDIT: As @phooji pointed out, this notion of traits is not just used by the STL, nor is it specific to C++.
As a completely shameless self-promotion, a while back I wrote
(a type of radix tree ) that uses traits to store strings of any type and using whatever comparison type the client wants them to store.
It might be an interesting read if you want to see an example of where this is used in practice.
EDIT: In response to your claim that std::string doesn't use traits::length, it turns out that it does in a few places.
Most notably, when you construct a std::string out of a char* C-style string, the new length of the string is derived by calling traits::length on that string.
It seems that traits::length is used mostly to deal with C-style sequences of characters, which are the "least common denominator" of strings in C++, while std::string is used to work with strings of arbitrary contents.
200k44499754
Your Answer
Sign up or
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Post as a guest
By posting your answer, you agree to the
Not the answer you&#39;re looking for?
Browse other questions tagged
Stack Overflow works best with JavaScript enabled}

我要回帖

更多关于 stl各容器的实现原理 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信