在stl中map,set内部都是使用相同的红黑树实现,map对应模板参数key_type,mapped_type,而set对应模板参数没有mapped_type

两者都支持insert操作

pair<iterator, bool> insert(const value_type& value);

 
 

对于map

typedef pair<key_type, mapped_type> value_type;

对于set

typdef key_type value_type;

 
 

那么在扩展库pb_ds中(代码在ext/pb_ds)

是这样设计的,比如trie

trie<string, int> 表示key是string,mapped 是int

trie<string, null_type> 表示key是string 没有mapped 类似一个TrieSet的概念。

那么是怎样做到这些的呢,比如自己写一个trie的结构,如何更好的避免TrieMap,TrieSet的实现代码重复,同时能提供两种实现(TrieSet没有mapped占用更少空间)。

 
 

除了模板类常用的技巧traits和tag forward之外,这里用到了#define #endef的技巧,先看下folly的一个

关于FBVector的test。

在test的.h中

TESTFUN(clause_23_3_6_1_1) {

VECTOR v;

EXPECT_TRUE(v.empty());

VECTOR::allocator_type a;

VECTOR v1(a);

EXPECT_TRUE(v1.empty());

}

 
 

在test的cpp中

typedef vector<int> IntVector;

typedef fbvector<int> IntFBVector;

typedef vector<folly::fbstring> FBStringVector;

typedef fbvector<folly::fbstring> FBStringFBVector

 
 

#define VECTOR IntVector

#include <folly/test/FBVectorTestBenchmarks.cpp.h> // nolint

#undef VECTOR

#define VECTOR IntFBVector

#include <folly/test/FBVectorTestBenchmarks.cpp.h> // nolint

#undef VECTOR

#define VECTOR FBStringVector

#include <folly/test/FBVectorTestBenchmarks.cpp.h> // nolint

#undef VECTOR

#define VECTOR FBStringFBVector

#include <folly/test/FBVectorTestBenchmarks.cpp.h> // nolint

#undef VECTOR

 
 

pb_ds也是类似的方法

#define PB_DS_DATA_TRUE_INDICATOR

#define PB_DS_V2F(X) (X).first

#include <ext/pb_ds/detail/pat_trie_/pat_trie_.hpp>

#undef PB_DS_DATA_TRUE_INDICATOR

#undef PB_DS_V2F

 
 

#define PB_DS_DATA_FALSE_INDICATOR

#define PB_DS_V2F(X) (X)

#include <ext/pb_ds/detail/pat_trie_/pat_trie_.hpp>

#undef PB_DS_DATA_FALSE_INDICATOR

#undef PB_DS_V2F

这里看下pat_trie_.hpp

#ifdef PB_DS_DATA_TRUE_INDICATOR

#define PB_DS_PAT_TRIE_NAME pat_trie_map

#endif

 
 

#ifdef PB_DS_DATA_FALSE_INDICATOR

#define PB_DS_PAT_TRIE_NAME pat_trie_set

#endif

 
 

template<typename Key, typename Mapped, typename Node_And_It_Traits,

typename _Alloc>

class PB_DS_PAT_TRIE_NAME :

 
 

也就是其实两次#include pat_trie_.hpp分别定义了

pat_trie_map和pat_trie_set

 
 

看看class PB_DS_PAT_TRIE_NAME内部

inline std::pair<point_iterator, bool>

insert(const_reference);

 
 

inline mapped_reference

operator[](key_const_reference r_key)

{

#ifdef PB_DS_DATA_TRUE_INDICATOR

return insert(std::make_pair(r_key, mapped_type())).first->second;

#else

insert(r_key);

return traits_base::s_null_type;

#endif

}

 
 

看下这个insert的实现
pat_trie_/insert_join_fn_imps.hpp

PB_DS_CLASS_T_DEC

inline std::pair<typename PB_DS_CLASS_C_DEC::iterator, bool>

PB_DS_CLASS_C_DEC::

insert(const_reference r_val)

{

node_pointer p_lf = find_imp(PB_DS_V2F(r_val));

if (p_lf != 0 && p_lf->m_type == leaf_node &&

synth_access_traits::equal_keys(PB_DS_V2F(static_cast<leaf_pointer>(p_lf)->value()), PB_DS_V2F(r_val)))

{

PB_DS_CHECK_KEY_EXISTS(PB_DS_V2F(r_val))

PB_DS_ASSERT_VALID((*this))

return std::make_pair(iterator(p_lf), false);

}

 
 

PB_DS_CHECK_KEY_DOES_NOT_EXIST(PB_DS_V2F(r_val))

 
 

leaf_pointer p_new_lf = s_leaf_allocator.allocate(1);

cond_dealtor cond(p_new_lf);

 
 

new (p_new_lf) leaf(r_val);

apply_update(p_new_lf, (node_update*)this);

cond.set_call_destructor();

branch_bag bag;

bag.add_branch();

m_p_head->m_p_parent = rec_join(m_p_head->m_p_parent, p_new_lf, 0, bag);

m_p_head->m_p_parent->m_p_parent = m_p_head;

cond.set_no_action_dtor();

++m_size;

update_min_max_for_inserted_leaf(p_new_lf);

_GLIBCXX_DEBUG_ONLY(debug_base::insert_new(PB_DS_V2F(r_val));)

PB_DS_ASSERT_VALID((*this))

return std::make_pair(point_iterator(p_new_lf), true);

}

 
 

OK,就是这么个意思了。。 map里面使用的时候PB_DS_V2F是 x.first 而set里面使用PB_DS_V2F就是x本身。

 
 

 
 

用#define来实现多份近似代码 - map,set中的应用的更多相关文章

  1. Don’t Put View Code Into Your View Controller别把View创建的代码放在VC中(swift)

    Don't Put Into Your View Controller别把View创建的代码放在VC中html, body {overflow-x: initial !important;}.Code ...

  2. 在linux服务器centos上使用svn同步代码到项目中

    一.需求 1.在多人开发过程中代码的管理以及版本的控制是一个很重要的问题,因为在开发过程中我们可能会同时更改过某个文件或者更改过多个文件, 这会导致我们很容易发生错误.所以我们需要一个方式去管理我们的 ...

  3. 知道创宇爬虫题--代码持续更新中 - littlethunder的专栏 - 博客频道 - CSDN.NET

    知道创宇爬虫题--代码持续更新中 - littlethunder的专栏 - 博客频道 - CSDN.NET undefined 公司介绍 - 数人科技 undefined

  4. warning: C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失

    ------问题-------------------- Qt项目使用 VC++ 编译器出现此错误. warning: C4819: 该文件包含不能在当前代码页(936)中表示的字符.请将该文件保存为 ...

  5. 从B站的代码泄露事件中,我们能学到些什么?

    先声明一下,本文不聊ISSUE中的七七八八,也不聊代码是否写的好,更不聊是不是跟蔡徐坤有关之类的吃瓜内容.仅站在技术人的角度,从这次的代码泄露事件,聊聊在代码的安全管理上,通常都需要做哪些事来预防此类 ...

  6. 在下载SOPC代码的过程中遇到的一些错误

    (1)Error (209015): Can't configure device. Expected JTAG ID code 0x02D120DD for device 2, but found ...

  7. 用C代码简要模拟实现一下RPC(远程过程调用)并谈谈它在代码调测中的重要应用【转】

    转自:http://blog.csdn.net/stpeace/article/details/44947925 版权声明:本文为博主原创文章,转载时请务必注明本文地址, 禁止用于任何商业用途, 否则 ...

  8. 金蝶K3,名称或代码在系统中已被使用,由于数据移动,未能继续以NOLOCK方式扫描

    使用金蝶K3时出现:名称或代码在系统中已被使用:错误代码:3604(E14H)source:Microsoft OLE DB provider for SQL SERVERDetail:由于数据移动, ...

  9. 【lombok】使用lombok注解,在代码编写过程中可以调用到get/set方法,但是在编译的时候无法通过,提示找不到get/set方法

    错误如题:使用lombok注解,在代码编写过程中可以调用到get/set方法,但是在编译的时候无法通过,提示找不到get/set方法 报错如下: 解决方法: 1.首先查看你的lombok插件是否下载安 ...

随机推荐

  1. C++笔试题(转)

    http://blog.csdn.net/hxz_qlh/article/details/16864567 这里面列举的题考察的东西都非常细,包括strcpy,字符串,大.小端的判断,很容易犯错,值得 ...

  2. Android 创建内容提供器(ContentResolver)

    如果想实现跨程序共享数据的功能,官方推荐的方式就是使用内容提供器,可以通过新建一个类去继承 ContentResolver 的方式来创建一个自己的内容提供器. ContentProvider 类中有六 ...

  3. 2.7---判断链表是否是回文(CC150)

    注意,如果用的方法是翻转整个链表,那么链表都被改变了.就无法做了. 此外注意fast.next.next!= null;不然也会报错.要保证后面的比前面的少. 答案: public static bo ...

  4. python之路一

    Python前世今生 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC ...

  5. MySQL表结构及数据的备份

    1.Navicat for MySQL 选择要保存的表,右键转储SQL文件,导出的sql文件中包括表的定义和表的数据两部分. 其他办法: (1) create table dust select * ...

  6. redis配置文件redis.conf参数说明

    redis配置文件redis.conf参数说明 (2013-01-09 21:20:40)转载▼ 标签: redis配置 redis.conf 配置说明 杂谈 分类: nosql # By defau ...

  7. centos7.0 安装LNMP运行环境

    LNMP作为php流行的运行环境,而最近需要搭建一个内部的php论坛.记录下LNMP的安装: 1.安装mysql 请参考:centos7 安装mysql5.7.11注意事项 2.安装php yum i ...

  8. iOS 在类别里添加成员变量的方法:objc_setAssociatedObject

    今天在github上查看MJPopupViewController这个项目,发现里面用到了objc_setAssociatedObject,用来为类别添加成员变量. 我百度之后,发现有人是这样说明的: ...

  9. IT笔试题

    史上最发散的软件工程师笔试题 1.请编写代码实现如下逻辑:有一只猫和多只老鼠,猫叫了一声,老鼠都吓跑了. 2.请介绍一种数据结构和算法,代表你在这个领域的能力. 3.请从正反两面介绍一下你对代码质量的 ...

  10. 我刚知道的WAP app中meta的属性(转载)

    之前我一直做的都是WEB前端开发,来北京以后面试了一个移动前端开发,WAP前端开发. 其实在原来公司的时候也做过这方面的开发,可面试的时候面试官问我,要想强制让文档与设备的宽度保持1:1,mate标签 ...