boost 学习笔记 10:Python

项目中需要将C++的程序暴露给网络使用,我也不想使用C++来用网络编程,就想到可以使用Python来解决Web端,然后将 C++ 的接口暴露给 Python 。于是在寻求解决方案的时候找到了 boost.python 库。

boost 中的 Python 库支持在 Python 和 C++ 之间的自由转换,包括 C++ 到 Python 的类型转换,默认参数,关键字参数,引用,指针等等。boost.python 库可以让 Python 轻易地调用 C++ 编写的模块,也可以很容易地在 C++ 中调用 Python 。

使用

C++ 文件中需要包含头文件

#include <boost/python.hpp>
using namespace boost::python;

还需要在链接的时候,加入 -lboost_python

以下操作借助Linux下g++完成,Windows可能需要借助其他工具,导出C++函数具体实现:

hello.cpp

char const* greet()
{
    return "hello, world";
}

#include <boost/python.hpp>

BOOST_PYTHON_MODULE(hello)			// Python 模块开始
{
    using namespace boost::python;		// 打开命名空间
    def("greet", greet);
}

Makefile

PYTHON_VERSION = 2.7
PYTHON_INCLUDE = /usr/include/python$(PYTHON_VERSION)

# location of the Boost Python include files and library
#  
BOOST_INC = /usr/local/include
BOOST_LIB = /usr/local/lib

# compile mesh classes
TARGET = hello

$(TARGET).so: $(TARGET).o
    g++ -shared $(TARGET).o -L$(BOOST_LIB) -lboost_python -L/usr/lib/python$(PYTHON_VERSION)/config -lpython$(PYTHON_VERSION) -o $(TARGET).so

$(TARGET).o: $(TARGET).cpp
    g++ -I$(PYTHON_INCLUDE) -I$(BOOST_INC) -fPIC -c $(TARGET).cpp

clean:
    rm *.so *.o

hello.py

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import hello
print hello.greet()

输出: hello, world

注意将 python, boost 所在目录 include 进去,在链接时加上 -lboost_python -lpython2.7 并 include python 和 boost目录。

Demo 地址GitLab : https://gitlab.com/einverne/boost_test/


2016-01-16 boost , C++

删除社交账号状态

这两天陆陆续续通过一些插件脚本删除了一些社交网站数据。年轻的时候发过一些无聊的状态,然后很久以后都没有登陆过的一些账号,倒不如关了的好,自此以后墙外只用 Google+ , 还有 Blog 记录一下所思所想,墙内公开内容除了豆瓣可能也没得发了,不愿生活在一个审查的制度下。虽然我可能也不会发什么敏感的内容,可谁知道什么敏感,什么不敏感呢?

facebook

Delete all facebook posts , 可以利用以下插件删除 Facebook 所有状态,包括账号内的头像等等。

Chrome Extension link

https://chrome.google.com/webstore/detail/facebook-timeline-cleaner/lfejocdlmhhkmnabbaeckmaehmgaffje

Update: 可惜了这个插件被删除了

renren

关闭账号

weibo

delete tool 删除工具 http://app.weibo.com/detail/62A7lB

批量删除 weibo http://3.amfen.sinaapp.com/

删除微博评论 http://weibo333.com/

腾讯微博

设置中关闭账号

关闭 QQ 空间

通过以下链接申请删除 QQ 空间。

http://imgcache.qq.com/qzone/web/qzone_submit_close.html


2016-01-15 经验总结 , social , posts

间谍之桥 感悟

间谍之桥 Bridge of Spies 2015 影评

一名伟大的律师,成就一件伟大的人质交换。剧情7分,表演8分,娱乐7分。汤姆汉克斯的演技自然没得说,不过俄国人质的更加深入人心,虽然并不知道他的名字,但之后就再不会忘记他的名字 —- Mark Rylance 。而电影在娱乐性方面给人更多的是思考,沉浸在那段历史中,思考的是那段历史中人们做过的每一个决策。

原本以为这部影片是讲述“间谍”之间的故事,看到开场辩护时就知道被标题所骗。联系到最近的快播案,两国在司法上可谓天上地下。从1957年的《十二怒汉》开始,到这部《间谍之桥》50多年间好莱坞从未放弃探讨司法的公平性。而前半部分的辩护差点让我以为电影会从间谍故事转变成法庭辩护。幸而在后面美国侦察机被炸到苏联土地等情节,才让故事走上交换人质的主线。也让电影变得更加主旋律。

电影中最棒的两段台词:

第一段出现在CIA希望Donovan背弃律师的誓言泄露被告的信息时,Donovan告诉CIA探员的话:

I’m Irish, you’re German, but what makes us both Americans? Just one thing, one one one. The rule book. We call it the Constitution. We agree to the rules, and that’s what makes us Americans, it’s all that makes us Americans.

第二段是 Donovan和 Abel 之间的对话。

DONOVAN: You don’t seem alarmed. ABEL: Would it help?

电影剧本下载地址


2016-01-13 movie , 思考感悟 , american , action

每天学习一个命令:su 切换身份或者使用 superuser

su 用来切换身份或者升级成使用 superuser。如果没有加任何参数,则 su 默认变为 superuser。

参数格式

    su [options] [username]

su 命令用来改变当前登录 session 的用户身份。直接使用 su 默认成为 superuser,使用参数 su - 短横线,则完全切换成该用户登录的状态,连同环境变量一同切换,工作目录也会切换。

-c 指令  或 --command= 指令 :执行完指定的指令后,即恢复原来的身份; 
-f 或——fast:适用于 csh 与 tsch,使 shell 不用去读取启动文件; 
- 或 -l 或——login:改变身份时,也同时变更工作目录,以及 HOME,SHELL,USER,logname。此外,也会变更 PATH 变量; 
-m,-p 或 --preserve-environment:变更身份时,不要变更环境变量; 
-s 或 --shell=:指定要执行的 shell; 

使用

切换用户而不切换工作目录

whoami   # 显示当前用户
einverne
pwd  # 当前目录
/home/einverne
su root # 切换到 root 用户
Password:
ev einverne # whoami
root
ev einverne # pwd
/home/einverne
ev einverne # exit
exit

切换用户并切换工作目录

whoami
einverne
pwd
/home/einverne
su -
Password:
ev ~ # pwd  # 注意此目录
/root
ev ~ #

2016-01-12 linux , command , su , superuser

boost 学习笔记 8:算法

对应书中第8章 算法,这一章作者介绍的很简单,只是举例使用 foreach , minmax ,其他算法都略去了。

foreach

将C++的语法扩充,使用 foreach 循环变量。

需包含头文件

#include <boost/foreach_hpp>

具体用法:

#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/assign.hpp>
#include <boost/foreach.hpp>
using namespace boost;
using namespace std;

int main(int argc, const char * argv[]) {

    using namespace boost::assign;
    vector<int> v = (list_of<int>(1),2,3,4,5);

    /**
     * 第一个参数 VAR 是循环变量声明 想要高效地使用序列内元素或者修改序列,需要声明使用引用
     * 第二个参数 COL 是要遍历的序列
     *
     */
    BOOST_FOREACH(int x, v){
        cout << x << "-";
    }
    cout << endl;

    string str("hello world");
    BOOST_FOREACH(char& c, str){
        cout << c << "-";
    }
    cout << endl;

    // use typeof
    BOOST_TYPEOF(*v.begin()) y;             // BOOST_AUTO(y, *v.begin())
    BOOST_FOREACH(y, v){
        cout << y << ",";
    }
    cout << endl;

    return 0;
}

minmax

在同一次操作中同时获取最大最小值。需包含头文件:

#include <boost/algorithm/minmax.hpp>
using namespace boost;

具体用法:

#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/assign.hpp>
#include <boost/algorithm/minmax_element.hpp>
using namespace boost;
using namespace std;

int main(int argc, const char * argv[]) {

    using namespace boost::assign;

    vector<int> v = (list_of(543), 90, 23, 42, 3, 10);

    BOOST_AUTO(x ,boost::minmax_element(v.begin(), v.end()));
    cout << "min: " << *x.first << endl;
    cout << "max: " << *x.second << endl;

    // first_min_element  找到第一个最小值
    // last_min_element 最后一个最小值

    return 0;
}

2016-01-12 boost , C++

boost 学习笔记 7:property_tree

上一篇文章boost容器中留下一个property_tree 没有学,觉得既然 boost 提供了 property_tree 这样好的工具来给C++ 解析xml和Json,必须要留有一定的篇幅来讲它。

原先项目中使用到JSON,需要使用C++解析一段返回值, JSON 格式如下:

{
  "ret": "101",
  "error": [
    {
      "errortype": "A0001",
      "errorstroke": {
        "0": "0.2",
        "1": "0.3"
      }
    },
    {
      "errortype": "A0021",
      "errorstroke": {
        "0": "0.2",
        "1": "0.3"
      }
    }
  ]
}

error 字段是一个数组,数组中的每个元素都是一个对象Object,每个Object中是一个键值对,其中 errorstroke 同样包含一个对象。我们都知道JSON只包含三种数据结构,矢量,数组和映射(参考),这样无疑给我们的解析工作带来很多遍历,这三种数据结构几乎可以将时间所有的信息包含进去。

下面就是解析这段 JSON 字符串的具体代码:(注意将JSON字符串 escape)

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include <string>

using namespace boost::property_tree;

int main(int argc, const char * argv[]) {

    std::string str_json = "{\"ret\":\"101\",\"error\":[{\"errortype\":\"A0001\",\"errorstroke\":{\"0\":\"0.2\",\"1\":\"0.3\"}},{\"errortype\":\"A0021\",\"errorstroke\":{\"0\":\"0.2\",\"1\":\"0.3\"}}]}";

    ptree pt;                       //define property_tree object
    std::stringstream ss(str_json);
    try {
        read_json(ss, pt);          //parse json
    } catch (ptree_error & e) {
        return 1;
    }

    std::cout << pt.get<std::string>("ret") << std::endl;
    ptree errortype = pt.get_child("error");            // get_child to get errors

    // first way
    for (boost::property_tree::ptree::iterator it = errortype.begin(); it != errortype.end(); ++it) {
        std::cout << it->first;
        std::cout << it->second.get<std::string>("errortype") << std::endl;
        ptree errorstroke = it->second.get_child("errorstroke");
        for (ptree::iterator iter = errorstroke.begin(); iter != errorstroke.end(); ++iter) {
            std::string key = iter->first;
            std::cout << iter->first << std::endl;
            std::cout << iter->second.data() << std::endl;
        }
    }

    // second way: using boost foreach feature
//    BOOST_FOREACH(ptree::value_type &v, errortype){
//        ptree& childparse = v.second;
//        std::cout << childparse.get<std::string>("errortype") << std::endl;
//        ptree errorstroke = childparse.get_child("errorstroke");
//        BOOST_FOREACH(ptree::value_type& w, errorstroke){
//            std::cout << w.first << std::endl;
//            std::cout << w.second.data() << std::endl;
//        }
//    }
    return 0;
}

代码的输出:

 101
 A0001
 0
 0.2
 1
 0.3
 A0021
 0
 0.2
 1
 0.3

再换用另外一段 JSON 尝试解析,从下面这段 JSON 中能够轻易的看出 JSON 内部的结构,支持的数据结构和类型:

{
  "array": [
    1,
    2,
    3
  ],
  "boolean": true,
  "null": null,
  "number": 123,
  "object": {
    "a": "b",
    "c": "d",
    "e": "f"
  },
  "string": "Hello World"
}

具体解析代码:

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include <string>
using namespace std;
using namespace boost::property_tree;

int main(int argc, const char * argv[]) {

    std::string str_json = "{\"array\":[1,2,3],\"boolean\":true,\"null\":null,\"number\":123,\"object\":{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"},\"string\":\"Hello World\"}";

    ptree pt;                       //define property_tree object
    std::stringstream ss(str_json);
    try {
        read_json(ss, pt);          //parse json
    } catch (ptree_error & e) {
        return 1;
    }

    ptree arraypt =pt.get_child("array");
    for (boost::property_tree::ptree::iterator it = arraypt.begin(); it != arraypt.end(); ++it) {
        cout << it->second.data() << " ";
    }
    cout << endl;

    std::cout << pt.get<bool>("boolean") << std::endl;
    std::cout << pt.get<std::string>("null") << std::endl;
    std::cout << pt.get<int>("number") << std::endl;
    std::cout << pt.get<std::string>("string") << std::endl;
    ptree opt = pt.get_child("object");

    BOOST_FOREACH(ptree::value_type &v, opt){
        cout << v.first << " : ";
        cout << v.second.data() << endl;
    }

    return 0;
}

利用 Boost property_tree 构造 JSON 字串,以下代码能够构造上面的JSON:

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include <string>
using namespace std;
using namespace boost::property_tree;

int main(int argc, const char * argv[]) {

    std::string str_json = "{\"array\":[1,2,3],\"boolean\":true,\"null\":null,\"number\":123,\"object\":{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"},\"string\":\"Hello World\"}";

    ptree root, arr,object;
    arr.push_back(std::make_pair("","1"));
    arr.push_back(std::make_pair("","2"));
    arr.push_back(std::make_pair("","3"));

    object.put("a","b");
    object.put("c","d");
    object.put("e","f");

    root.add_child("array", arr);
    bool boolvalue = true;
    root.put("boolean",boolvalue);
    root.put("null","null");
    int num = 123;
    root.put("number",num);
    root.add_child("object",object);
    root.put("string","Hello World");

    //write_json("out.json", root);
    stringstream s;
    write_json(s, root, false);
    string out = s.str();
    cout << out ;
    return 0;
}

两个有用的JSON工具:

Boost property_tree 解析 XML 可参考这篇文章 ,解释得非常清楚。


2016-01-11 boost , C++

每天学习一个命令:apt 安装卸载软件

APT 是 Advanced Packaging Tools 的缩写,是 Debian 及其派生的发行版(使用最广泛的 Ubuntu/Linux Mint 等等)的软件包管理器。 APT 可以自动下载、配置和安装二进制或源代码格式软件包,简化了 Unix 系统上管理软件的过程。 APT 最早被设计成 dpkg 的前端,用来处理 deb 格式的软件包。

APT 主要由以下几个命令组成:

  • apt-get
  • apt-cache
  • apt-file

APT 能够自动处理软件的依赖问题,大大简化了工作流程

这里主要讲 apt-get 的常见用法

常用命令

搜索软件包

apt search package_name

安装软件包

apt install package

更新源

自动根据 /etc/apt/sources.list 中的设定,以及 /etc/apt/sources.list.d 目录下的设定,更新软件资料源。

sudo apt update

使用如下命令安装更新

sudo apt upgrade

移除软件源

apt remove package  # 移除软件包,但是保留配置文件
apt purge package #移除软件包并移除配置
apt autoremove # 移除孤立的并不被依赖的软件包

列出软件清单

apt list

升级系统

sudo apt-get dist-upgrade

最后如果还有什么不明了的,可以 man apk

前端界面

我目前使用

  • Synaptic

reference


2016-01-11 apt , linux , command , ubuntu

boost 学习笔记 6:容器

对应书中的第七章容器与数据结构。先是讲了五个容器: array , dynamic_bitset, unordered, bimap和 circular_buffer. 他们都是对标准容器的扩充。

  • array 是对 C++内建数组的简单包装
  • dynamic_bitset 可容纳任意数量的二进制位
  • unordered 实现散列容器,非二叉树实现
  • bimap 是双向 map 扩展了std::map 的内容
  • circular_buffer 是循环队列。

tuple, any 和 variant 能够容纳不同类型容器

  • tuple 是对 std::pair 的泛化
  • any和 variant 都只能容纳一个可变类型的容器。any 可以持有任何类型数据,variant 需要在编译期指定类型。

最后 multi_arrayproperty_tree 两个组件使用组合模式实现复杂的数据结构。 multi_array 是一个泛型多维容器, property_tree 出自 1.41 版,可以解析 xml, son, ini 和 info 四种格式文件,在内部构造属性树。

对容纳元素基本要求:析构函数不能抛出异常

array

数组容器,包装了 C++ 内建数组,为其提供标准 STL 容器接口,begin(), front() 等等,性能与原始数组相差不大。但是 array 功能有限,当需要可变容量数组时,还是需要借助 std::vector 或者 boost::scoped_array

array 主要缺陷:

  • 没有构造函数,不能指定大小和初值
  • 没有 push_back() 和 push_front() ,不能动态增长
  • 不能搭配插入迭代器适配器功能

需包含头文件

#include <boost/array.hpp>
using namespace boost;

具体用法:

#include <iostream>
#include <boost/array.hpp>
#include <boost/typeof/typeof.hpp>
using namespace boost;

int main(int argc, const char * argv[]) {
    // 赋值
    array<int, 5> myArray;
    myArray[1] = 2;
    myArray.front() = 1;
    myArray.back() = 5;

    // 获取指针
    int* p = myArray.c_array();
    *(p+2) = 3;

    for (array<int,5>::iterator itr = myArray.begin(); itr != myArray.end(); ++itr) {
        std::cout << *itr << std::endl;
    }

    array<int, 10> arr2;
    arr2.assign(5);
    for (BOOST_AUTO(pos, arr2.begin()); pos != arr2.end(); ++pos) {
        std::cout << *pos << ",";
    }

    // 类似数组的初始化
    array<int, 3> ar3= { 1, 2, 3 };
    array<int, 10> ar4 = {0};           // all element equal 0
    array<std::string, 5> ar5= {"first"};  // 初始化第一个元素

    return 0;
}

dynamic_bitset

C++98 标准为处理二进制提供了两个工具: vector 和 bitset. 他们各自有优缺点: vector 可以动态增长,但不能方便地进行位运算;而 bitset 则刚好相反,可以方便地对容纳的二进制做位运算,但不能动态增长。 dynamic_bitset 正好填补了两者之间的空白。

需包含如下头文件

#include <boost/dynamic_bitset.hpp>
using namespace boost;

unordered

unordered 库提供两个散列集合类 unordered_setunordered_multiset ,同样 STLport 库也提供 hash_set 和 hash_multiset. 他们接口、用法和 STL 中标准关联容器 set/multiset 相同,只是内部使用散列代替二叉树实现,因此查找复杂度由对数降为常数。

散列容器 hash container 比二叉树的存储方式可以提供更高的访问效率。boost.unordered 库提供了一个完全符合 C++ 新标准草案 TR1 的散列容器实现,包括无序集合 set 和 无序映射 map.

unordered 库提供两个散列映射类 unordered_mapunordered_multimap ,同样 STLport 中也提供了 hash_map/hash_multimap. 他们的接口、用法和 STL 中的标准关联容器 map/multimap 相同,只是内部使用散列表代替了二叉树。

#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
using namespace boost;

代码:

#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
using namespace boost;
using namespace std;

int main(int argc, const char * argv[]) {
    // 散列集合类
    using namespace boost::assign;
    using namespace boost::unordered;

    // 散列集合
    unordered_set<string> s = (list_of<string>("one")("two")("three"));
    s.insert("four");
    s.erase("two");
    unordered_set<string>::iterator it = s.find("one");
    s.erase(it);
    for (unordered_set<string>::iterator itr = s.begin(); itr != s.end(); ++itr) {
        cout << *itr << endl;
    }
    s.empty();


    // 关联式容器
    unordered_map<int, std::string> um = map_list_of(1,"one")(2,"two")(3,"three");
    um.insert(std::make_pair(10,"ten"));
    um[11] = "eleven";
    um[15] = "fifteen";

    std::cout << um[15] << std::endl;
    BOOST_AUTO(p, um.begin());
    for (p; p!= um.end(); ++p) {
        cout << p->first << "-" << p->second << ",";
    }
    cout << endl;

    um.erase(11);               // delete key 11
    cout << um.size() << endl;

    // stl map
    map<int, std::string> stdmap;
    // assignment
    stdmap.insert(map<int, std::string>::value_type(1, "one"));
    stdmap.insert(std::pair<int, std::string>(2, "two"));
    stdmap.insert(std::make_pair(3, "three"));
    stdmap[4] = "four";

    map<int, std::string>::iterator pos;
    for (pos = stdmap.begin(); pos != stdmap.end(); ++pos) {
        std::cout<< "key: " << pos->first << "\t"
            << "value: " << pos->second << "\n";
    }

    stdmap.erase(4);
    cout << "map size " << stdmap.size() << endl;

    return 0;
}

bimap

可以容纳两个类型的元素,类似于 C++标准提供的映射型容器 map 和 multi_map ,但是 C++标准中的关联数组,只是将一个 key 映射到一个 value, 这种关系是单向的,只能从 key 到 value 而不能反过来。因此 boost.bimap 扩展了标准库的映射型容器,提供双向映射的能力。

对于 bimap<X, Y> , bimap.let 相当于 map<X, Y> ,而 bimap.right 相当于 map<Y, X>

bimap<collection_type_of<X>, collection_type_of<Y> >

这个概念下, std::map 和 std::multi_map 的左值是一个有序的集合,而右组无任何约束,对应的 bimap 是:

bimap< set_of<X> , unconstrained_set_of<Y> > 和 bimap<multiset_of<X>, unconstrained_set_of<Y> >

bimap 定义的集合类型包括如下:

  • set_of 可以作为键值 索引,有序且唯一,视图相当于 map
  • multiset_of 可以用作键值 索引,有序不唯一 ,视图相当于 multimap
  • unordered_set_of 可以作为键值,无序且唯一,视图相当于 unordered_map
  • unordered_multiset_of 可以作为键值,无序不唯一,视图相当于 unordered_multimap
  • list_of 不能作为键值,序列集合,无对应 STL 容器
  • vector_of 不能作为键值,随机访问集合,无对应 STL 容器
  • unconstrained_set_of 不能作为键值,无任何约束关系,无对应 STL 容器

bimap 可以使用 using namespace tags; tagged类给左组和右组数据在语法层面加上“标签”。标签的定义如下:

template< class Type, class Tag>
struct tagged {
    typedef Type value_type;
    typedef Tag tag;
};

tagged<int , struct id> 表示包装了 int 类型 ,标签名字是 id.

#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/bimap.hpp>
#include <boost/bimap/list_of.hpp>
#include <boost/bimap/unordered_set_of.hpp>
#include <boost/bimap/multiset_of.hpp>
#include <boost/bimap/list_of.hpp>
#include <boost/bimap/vector_of.hpp>
#include <boost/bimap/unconstrained_set_of.hpp>
#include <boost/assign.hpp>
using namespace boost;
using namespace std;

template< typename T>
void print_map(T& m){
    for (BOOST_AUTO(pos, m.begin()); pos != m.end(); ++pos) {
        cout << pos->first << "<-->" << pos->second << endl;
    }
}

int main(int argc, const char * argv[]) {

    using namespace boost::bimaps;
    using namespace tags;
    // bimap
    bimap<int, string> bmap;

    bmap.left.insert(make_pair(1, "one"));

    bmap.right.insert(make_pair("two", 2));

    for (BOOST_AUTO(pos, bmap.left.begin()); pos != bmap.left.end(); ++pos) {
        cout << "left key: " << pos->first << " value: " << pos->second << endl;
    }

    // 类型集合位于名字空间 boost::bimaps, 需包含各自同名头文件,文件位于 <boost/bimap/list_of.hpp>
    // 左组是有序集合,右组是无序集合
    bimap<int, unordered_set_of< string > > bm1;

    // 左组和右组都是有序多值集合
    bimap< multiset_of<int> , multiset_of< string > > bm2;

    // 左组是无序集合,右组是一个序列,只能有左视图
    bimap< unordered_set_of<int> , list_of<string> > bm3;

    // 左组随机访问集合,右组无约束
    bimap< vector_of<int>, unconstrained_set_of< string > > bm4;

    bimap<tagged<int, struct id>, tagged<string, struct name> > bm;
    bm.by<id>().insert(make_pair(1, "Sam"));

    bm.by<name>().insert(make_pair("Tom", 2));

    print_map(bm.by<id>());

    typedef bimap<int, string> bm_t;

    using namespace boost::assign;
    bm_t bmt = assign::list_of<bm_t::relation>(1, "one")(2 , "two");

    BOOST_AUTO(pos, bmt.left.find(2));
    cout << "key: " << pos->first << "\t" << "value: "<< pos->second << endl;
    BOOST_AUTO(pos2, bmt.right.find("one"));
    cout << "key: " << pos2->first << "\t" << "value: " << pos2->second << endl;

    bmt.left.replace_key(pos, 22);
    bmt.left.replace_data(pos, "replaced two");

    print_map(bmt.left);

    return 0;
}

bimap 还有很多高级用法,等用到的时候查阅文档吧。

circular_buffer

循环缓冲区数据结构,大小固定的循环队列。固定大小的缓存容量,当新增加的元素超过缓冲区的容量时,自动将最初的元素覆盖。

tuple

tuple 元组 定义了固定数目元素的容器,其中每个元素类型都可以不相同,这与其他容器有本质的区别。

#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/assign.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp>
using namespace boost;
using namespace std;

int main(int argc, const char * argv[]) {

    typedef boost::tuple<int, string, double> my_tuple;
    my_tuple tuple0(1,"test");
    my_tuple tuple1 = tuple0;
    my_tuple tuple2;
    tuple2 = tuple0;

    my_tuple t1 = boost::make_tuple(2,"test",100.0);
    assert(t1.get<0>() == 2);
    assert(t1.get<1>() == "test");

    // 比较
    my_tuple t2 = boost::make_tuple(3,"test",200.00);
    assert(t1 < t2);

    // io
    cout << t1 << endl;
    cout << "input tuple: example: (1 test 200.0)"<<endl;
    cin >> t1;
    cout << t1 << endl;

    using namespace boost::assign;

    vector<my_tuple> v = tuple_list_of(1, "1", 1.0)(2, "2", 2.0);
    assert(v.size() == 2);

    return 0;
}

any

特殊容器,只能容纳一个元素,但这个元素可以是任意类型—— int , double, string, STL 容器或者任意自定义类型。程序可以用 any 保存任意的数据,在任何需要的时候将它取出来,这种功能与 shared_ptr<void> 有些类似,但 any 是类型安全的。 any 不是一个模板类。

不要用 any 保存原始指针,代替用 shared_ptr 智能指针。

当 any 以指针的方式传入 any_cast() 的时候,返回的指针类型与传入的 any 对象具有相同的常量。如果 any 不持有任何对象,这两个 any_cast() 不会抛出异常,而是返回一个空指针。

#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/assign.hpp>
#include <boost/any.hpp>
using namespace boost;
using namespace std;

// check object type in any
template< typename T>
bool can_cast(any &a){
    return typeid(T) == a.type();
}

// get value in any
template< typename T>
T& get(any &a){                     // &  不能丢失,否则无法修改 a 的值
    BOOST_ASSERT(can_cast<T>(a));
    return *any_cast<T>(&a);
}

template< typename T>
T* get_pointer(any &a){
    BOOST_ASSERT(can_cast<T>(a));
    return any_cast<T>(&a);
}

int main(int argc, const char * argv[]) {

    any a(10);
    int n = any_cast<int>(a);       // get value return a copy of a's data : 10
    // any_cast<double>(a) 	throw bad_any_cast
    assert(n == 10);

    a = string("test");
    a = vector<vector<int> >();

    a = n;
    assert(can_cast<int>(a));
    get<int>(a) = 11;                   // Will change a value this line
    *get_pointer<int>(a) = 12;

    return 0;
}

variant

与 any 类似,是可变类型,对 C++中 union 概念增强和扩展。

需要头文件:

#include <boost/variant.hpp>
using namespace boost;

例子:

#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/assign.hpp>
#include <boost/variant.hpp>
using namespace boost;
using namespace std;

int main(int argc, const char * argv[]) {

    typedef variant<int, double, string> var_t;
    var_t v;                                // v == 0
    assert(v.type() == typeid(int));
    assert(v.which() == 0);

    v = "test string";                      // v -> string
    cout << *get<string>(&v) << endl;       // get()

    try {
        cout << get<double>(v) << endl;
    } catch (bad_get &) {
        cout << "bad_get" << endl;
    }

    return 0;
}

variant 与 any 的区别

variant 和 any 都可以保存多类型的变量,但是他们的使用是有区别的。

  • 都可以容纳一个可变类型的元素,但是 variant 是有界类型,类型范围由用户指定,而 any 则是无界类型,可以容纳任意的类型
  • variant 可以在编译期类型检查
  • variant 提供泛型的 vistor 方式访问内部元素

multi_array

多维数组 的高效实现。 multi_array 是递归定义的。

#include <boost/multi_array.hpp>
using namespace boost;

具体用法:

#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/assign.hpp>
#include <boost/array.hpp>
#include <boost/multi_array.hpp>
#include <boost/multi_array/extent_gen.hpp>
using namespace boost;
using namespace std;

int main(int argc, const char * argv[]) {

    multi_array<int, 3> ma;             // 定义三维数组
    multi_array<int, 3> ma1(extents[2][3][4]);      // 定义维度 2/ 3/ 4 的三维数组

    for (int i=0 , v= 0; i < 2; ++i) {
        for (int j =0 ; j< 3; ++j) {
            for (int k  = 0; k < 4; ++k) {
                ma1[i][j][k] = v++;
            }
        }
    }

    boost::array<size_t, 3> idx = { 0,1,2};
    ma1(idx) = 10;
    cout << ma1(idx) << endl;

    boost::array<size_t, 3> arr = { 4,3,2};
    ma1.reshape(arr);

    for (int i = 0; i< ma1.shape()[0]; ++i) {
        for (int j = 0 ; j < ma1.shape()[1]; ++j) {
            for (int k = 0 ; k < ma1.shape()[2]; ++k) {
                cout << ma1[i][j][k] << ",";
            }
        }
    }

    ma1.resize(extents[2][9][9]);           // 改变多维数组的大小

    // 创建子视图
    /**
     * (0, 1, 2, 3)
     * (4, 5, 6, 7)
     * (8, 9, 10, 11)
     */

    typedef multi_array<int, 2> ma_type;
    multi_array<int, 2> mademo(extents[3][4]);
    for (int i = 0, v = 0; i< mademo.shape()[0]; ++i) {
        for (int j = 0 ; j < mademo.shape()[1]; ++j) {
            mademo[i][j] = v++;
        }
    }
    cout << endl;

    typedef ma_type::index_range range;
    indices[range(0,2)][range(0,2)];
    /**
     * (0, 1)
     * (4, 5)
     */

    BOOST_AUTO(view, mademo[indices[range(0,2)][range(0,2)] ]);
//    ma_type::array_view<2>::type view = ma[indices[range(0,2)[range(0,2)]];

    cout << view.num_dimensions() << endl;

    // 将一维数组适配成多维数组
    // 提供了 multi_array_ref 和 const_multi_array_ref
    // 适配完不能动态增长,其他和 multi_array 完全相同
    // const_multi_array_ref 功能少一些,因为它是只读的
    int arra[12];
    for (int i = 0; i < 12; ++i) {
        arra[i] = i;
    }
    multi_array_ref<int, 2> mar(arra, extents[3][4]);

    const_multi_array_ref<int, 2> cmar(arra, extents[2][6]);
    return 0;
}

property_tree

property_tree 容器比较复杂,它是一个保存了多个属性值得树形数据结构,功能强大,可以解析 xml, ini, json 和 info 四种格式的文本数据。单独拿一篇文章来讲它好了。


2016-01-10 boost , C++

星球大战:好莱坞流水线上的标准产物加上一些情怀催化一下

我果然不是星战迷,也没有星战情怀,相比同档期电影可以一看,但是我不是很喜欢这一部。 剧情6分(标准套路,困境解决困境),表演6.5(黑人演员可圈可点,女主没什么说的,机器人没有语言没有表情却异常的生动),娱乐性8分(一分光剑一分BB8)。

星战前六部,正传三部,前传三部,稍早的时候看过了,看原力觉醒之前没有认真补课。但是我知道好莱坞成熟流水线上的电影是不会要求你必须看完前六部再来看这一部电影的,每一部完整的电影都会有其完整的剧情和完整的人物描述。回到这一部原力觉醒,可能是星战迷内心的浴火被燃烧了,从第一部到今年三四十年的时间,足够让一个从青年变成中年甚至老年,伴随星战迷成长的电影总会伴随这一系列的讨论,今天早上看票房成绩已经是影史第四,超过票房第一的阿凡达已经是板上钉钉。基于这样的环境去影院看了。

剧情

就像之前说过的那样,这一部在剧情上的设定就是好莱坞标准的剧本设定,产生新的反派,然后需要正义人士组织反抗,制定计划一步一步瓦解反派,实在没有任何需要交代的内容。我甚至在观影过程中连续两次打哈欠,这实属罕见,在以前从来没有出现过,甚至在看《刺客聂隐娘》在场有人睡着的情况下我也没有困意,而这一部看到女主发觉拥有原力,Resistance组织开始制定作战计划开始就已经注定了结局。再到爱情,亲情的设定,总觉得会产生一些问题,大战刚刚结束,公主与将军的见面,再到后面父子的见面总感觉设定上有一些故意而为之。当然这些都是一些小的问题,总体来看剧情还是有一个及格的6分。至少前半部分,已经后面的一些情节,总能够让观众一边被主人公的台词表演逗笑,一边被剧情的紧张气氛而胆战心惊。

表演

再到表演,其实也并没有什么说得,反而到时那个萌萌的机器人能让观众会心一笑,有些时候表演并不需要语言和表情,一举一动都能够看出表演的出彩,或许这也是这部电影在表演上能给我留下的唯一印象,女主,黑人男主,再到哈里森福特,并没有什么特别出彩的地方。

BB 8

娱乐

观影风向标定下的娱乐性,其实一直不大明白,娱乐到底是指那一方面,如果是指话题性,新闻性,亦或是卖萌属性的话,就像上面说得那样我会一分给光剑,这一分给的是情怀,一分给BB8,那是因为这个“球”真是太可爱了,可爱到人人都会想要拥有一台。

总之这是一部让我觉得值得票价却也提不出什么优点的电影啦。感谢导演 JJ 艾布拉姆斯,感谢哈里森福特。


2016-01-09 思考感悟 , movie

guake zsh 配置小记

Guake is a drop-down terminal for the GNOME desktop which includes split terminal functionality, session save/restore, support for transparency, and many other features.

配置 zsh guake 小记

Install zsh

sudo apt-get update && sudo apt-get install zsh

Install Oh-my-zsh

wget –no-check-certificate https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O – | sh

Make zsh default shell

chsh -s $(which zsh)

Get oh-my-zsh config

From here: https://github.com/robbyrussell/oh-my-zsh

Change theme

Edit zshrc config vim ~/.zshrc

ZSH_THEME="agnoster"

Install missing fonts

Install missing fonts here: https://github.com/Lokaltog/powerline-fonts After install missing font, change terminal font to “Melon xx”.

Refresh font cache

fc-cache -f -v

Install solarized scheme to guake

According to this: https://github.com/coolwanglu/guake-colors-solarized git clone this repo and run ./set_dark solarized .

Some config of guake

  • F12 to toggle guake
  • F11 to toggle full screen

Tab management

  • Alt + T for new tab
  • Alt + W for close current tab
  • Alt + N to go to previous tab
  • Alt + P to go to next tab

Clipboard

  • Alt + C for copy text to clipboard
  • Alt + V for paste text from clipboard

Guake 自带的终端内搜索 Ctrl + Shift + F

finally

guake zsh

And here is another article about guake, I am taking some shorcut configs from this article. And if you want to build guake from source, you can take a look at thie article.

And all the source code: https://github.com/Guake/guake.

reference


2016-01-09 linux , guake , zsh , vim , agnoster , fonts , solarized

电子书

本站提供服务

最近文章

  • 从 Buffer 消费图学习 CCPM 项目管理方法 CCPM(Critical Chain Project Management)中文叫做关键链项目管理方法,是 Eliyahu M. Goldratt 在其著作 Critical Chain 中踢出来的项目管理方法,它侧重于项目执行所需要的资源,通过识别和管理项目关键链的方法来有效的监控项目工期,以及提高项目交付率。
  • AI Shell 让 AI 在命令行下提供 Shell 命令 AI Shell 是一款在命令行下的 AI 自动补全工具,当你想要实现一个功能,敲一大段命令又记不住的时候,使用自然语言让 AI 给你生成一个可执行的命令,然后确认之后执行。
  • 最棒的 Navidrome 音乐客户端 Sonixd(Feishin) Sonixd 是一款跨平台的音乐播放器,可以使用 [[Subsonic API]],兼容 Jellyfin,[[Navidrome]],Airsonic,Airsonic-Advanced,Gonic,Astiga 等等服务端。 Sonixd 是一款跨平台的音乐播放器,可以使用 [[Subsonic API]],兼容 Jellyfin,[[Navidrome]],Airsonic,Airsonic-Advanced,Gonic,Astiga 等等服务端。
  • 中心化加密货币交易所 Gate 注册以及认证 Gate.io 是一个中心化的加密货币交易所。Gate 中文通常被称为「芝麻开门」,Gate 创立于 2013 年,前身是比特儿,是一家致力于安全、稳定的数字货币交易所,支持超过 1600 种数字货币的交易,提供超过 2700 个交易对。
  • 不重启的情况下重新加载 rTorrent 配置文件 因为我在 Screen 下使用 rTorrent,最近经常调试修改 rtorrent.rc 配置文件,所以想要找一个方法可以在不重启 rTorrent 的情况重新加载配置文件,网上调查了一下之后发现原来挺简单的。