c++11 boost - 容器(3) circular_buffer、tuple

2018-07-12 11:09:42

circular_buffer 实现了循环缓冲区的结构,大小是固定的,在一开始就创建了内存,当容器达到末尾时,会自动循环到开头。

circular_buffer_space_optimized 类只有在确实需要时才分配内存空间,而且当容器内元素减少时会自动释放内存。一般适用于当程序需要容纳大量元素,但多数情况下只需要容纳少量元素。

// Copyright (c) 2015
// Author: Chrono Law
#include <iostream>
using namespace std;

#include <boost/assign.hpp>
#include <boost/circular_buffer.hpp>
using namespace boost;

void case1()
{
    circular_buffer<int> cb(5);
    assert(cb.empty());

    cb.push_back(1);
    cb.push_front(2);
    assert(cb.front() == 2);
    cb.insert(cb.begin(), 3);


    for (auto pos = cb.begin(); pos != cb.end();++pos)
    {   cout << *pos << ",";    }
    cout << endl;

    cb.pop_front();
    assert(cb.size() == 2);
    cb.push_back();
    assert(cb[0] = 2);

    //using namespace boost::assign;
    circular_buffer<int> cb1 = (assign::list_of(1),2,3);
    circular_buffer<int> cb2 = (assign::list_of(3),4,5);
    circular_buffer<int> cb3 = cb1;

    assert(cb1 < cb2);
    assert(cb1 == cb3);

}

template<typename T>
void print(T& cb)
{
    for (auto& x: cb)
    {   cout << x << ",";   }
    cout << endl;
}

void case2()
{
    circular_buffer<int> cb = (assign::list_of(1),2,3);
    print(cb);

    cb.push_back(4);
    print(cb);

    cb.push_back(5);
    print(cb);

    cb.pop_front();
    print(cb);

}

void case3()
{
    circular_buffer<int> cb =(assign::list_of(1),2,3,4,5);

    assert(cb.full());
    print(cb);

    int *p = cb.linearize();
    assert(p[0]== 1 && p[3] == 4);
    assert(cb.is_linearized());

    cb.rotate(cb.begin()+ 2);
    print(cb);

}

void case4()
{
    using namespace boost::assign;

    circular_buffer_space_optimized<int> cb( 10);
    push_back(cb)(1),2,3,4;

    assert(cb.size() == 4);
    assert(cb.capacity() == 10);

    cb.resize(100, 10);
    assert(cb.size() == cb.capacity());

}

int main()
{
    case1();
    case2();
    case3();
    case4();
}
[root@192 c++]# g++ -std=c++11 main.cpp 
[root@192 c++]# ./a.out 
3,2,1,
1,2,3,
2,3,4,
3,4,5,
4,5,
1,2,3,4,5,
3,4,5,1,2,


tuple(元组)定义了固定数目元素的容器,其中每个元素类型可以不同。它是 std::pair 的泛化。

tuple 默认最多只能支持10种数据类型,对于大多数场景已经够用。

tuple 可以代替 struct ,运行时性能差不多,只是编译时间略长(泛型编程的普遍现象)。

// Copyright (c) 2015
// Author: Chrono Law
#include <iostream>
#include <cassert>
//using namespace std;

#include <boost/core/ignore_unused.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp>
using namespace boost;

typedef tuple<int, std::string>    my_tuple1;
typedef tuple<int, my_tuple1> my_tuple2;

typedef tuple<void>             no_instance_t1;
typedef tuple<double(int)>  no_instance_t2;

void case1()
{
	//可以容纳int,string,double
    typedef tuple<int, std::string, double> my_tuple;
    my_tuple t1;
    my_tuple t2(1, "123");
    my_tuple t3(t1);
    t2 = t3;

    int x = 10;
    tuple<int&> t4(x);

    {
        tuple<void*> t1; //void *指针
        tuple<double(*)(int)> t2;  //函数指针
    }

    {
        boost::make_tuple(2, 3.0);  //int,double
        boost::make_tuple(std::string(), std::vector<int>());  //string,vector<int>

        int i;
        std::string s;
        tuple<int, std::string&>     t1       = boost::make_tuple(i, boost::ref(s));
        tuple<const int&, std::string&>  t2   = boost::make_tuple(boost::cref(i),boost::ref(s));

        boost::ignore_unused(t1, t2);
    }

}

//访问元组
void case2()
{
    auto t = make_tuple(1, "char[]", 100.0);

    assert(t.get<0>() == 1);
    assert(t.get<2>() == 100.0);

    std::cout << t.get<1>();
    std::cout << ++t.get<0>();

    std::cout << std::endl;

    get<0>(t);
    get<1>(t);

}

//比较操作,要求内部元素能够执行比较操作,且元组个数要相同
//根据字典序比较,一旦得出结果立即停止操作
void case3()
{
    typedef boost::tuple<int ,double ,std::string> my_tuple;    //3-tuple

    my_tuple t1 = boost::make_tuple(1, 100.0, std::string("abc"));
    my_tuple t2 = boost::make_tuple(1, 200.0, std::string("def"));
    assert(t1 < t2);

    my_tuple t3(t2);
    assert(t2 == t3);
}

//流
void case4()
{
    typedef boost::tuple<int ,double ,std::string> my_tuple;

    my_tuple t1(1, 2.0, "string");
    std::cout << t1 << std::endl;

    //std::cout << "please input tuple:";
    
    //(1,2.0,aaa)这种格式输入
    //std::cin >> t1;

    //std::cout << t1 << std::endl;
    
    //也可以自定义分隔符
    std::cout << tuples::set_open('[') << tuples::set_close(']');
    std::cout << tuples::set_delimiter(',');
    std::cout << t1 << std::endl;

}

//
typedef tuple<int ,double ,std::string> my_tuple;

my_tuple func()
{   return boost::make_tuple(1, 2.0, "string");}

void case5()
{
    int i;double d;std::string s;
    //解包赋值
    tie(i, d, s) = func();
    std::cout << i;
	
	//ignore代表忽略
    tie(tuples::ignore, d, tuples::ignore) = func();
    	
    //tie(i,s) = make_pair(100,"freecls")
}

//////////////////////////////////////////
#include <boost/assign.hpp>
void case6()
{
    typedef boost::tuple<int ,double ,std::string> my_tuple;
    using namespace boost::assign;

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

    v += boost::make_tuple(3, 3.0, "789"),boost::make_tuple(4, 4.0, "abc");
    assert(v.size() == 4);

}

//////////////////////////////////////////
template <typename Tuple>
void print_tuple(const Tuple& t)
{
    std::cout << t.get_head() << ',';  //输出首元素
    print_tuple(t.get_tail()); //递归输出剩余的元素
}
template<>
void print_tuple(const tuples::null_type&) {}

void case7()
{
    typedef boost::tuple<int , double ,std::string> t_type;
    t_type  t(1, 2.1, "string tuple");
    
    std::cout << std::endl;
    print_tuple(t);
    std::cout << std::endl;

}

//使用访问者模式
template<typename Visitor, typename Tuple>
typename Visitor::result_type
visit_tuple(Visitor v, const Tuple &t)
{
    v(t.get_head());
    return visit_tuple(v, t.get_tail());
};

struct print_visitor
{
    typedef void result_type;
    template<typename T>
        result_type operator()(const T &t)
        {
            std::cout << t << ",";
        }
};
template<>
void visit_tuple//< print_visitor,  tuples::null_type>
    (print_visitor , const tuples::null_type &)
    {}

template<typename T>
struct max_visitor
{
    T *tmp;                                             //最大值
    max_visitor(T *t):tmp(t){}
    typedef void result_type;
    result_type operator()(const T &t)
    {   *tmp = *tmp < t? t : *tmp;  }
};

template<>
void visit_tuple//< max_visitor<double>,  tuples::null_type>
(max_visitor<double> , const tuples::null_type &)
{}

void case8()
{
    boost::tuple<int , double ,std::string>  t(1, 2.1, "string visitor");
    visit_tuple(print_visitor(), t);

    {
        boost::tuple<int, long, float, double> t(100, 5, 3.14, 314.15);
        double *max_value = new double(t.get_head());
        max_visitor<double> mv(max_value);
        visit_tuple(mv, t);
        std::cout << *max_value  << std::endl;
    }

    typedef boost::tuple<int , std::string> my_tuple1;
    typedef boost::tuple<int, my_tuple1> my_tuple2;

    assert(typeid(int) == typeid(tuples::element<0, my_tuple1>::type));
    assert(typeid(std::string) == typeid(tuples::element<1, my_tuple1>::type));
    std::cout << tuples::length<my_tuple2>::value << std::endl;

}

int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
    case6();
    case7();
    case8();
}
[root@192 c++]# g++ -std=c++11 main.cpp 
[root@192 c++]# ./a.out 
char[]2
(1 2 string)
[1,2,string]
1
1,2.1,string tuple,
1,2.1,string visitor,314.15
2


 备注

1.编译器版本gcc4.8.5,运行环境centos7 64位
2.本文只做简单记录用,详细用法请参考 Boost Library,或者是罗剑锋的 boost程序库完全开发指南 书本
3..原文地址http://www.freecls.com/a/2712/a7


©著作权归作者所有
收藏
推荐阅读
简介
天降大任于斯人也,必先苦其心志。