首页 > 代码库 > 转发参数包的例子

转发参数包的例子

16.58 为你的StrVec类添加emplace_back函数。

StrVec.h(注意,函数模板和模板成员函数的定义和声明要放在一起,通常都放在头文件中)

#ifndef STRVEC_H#define STRVEC_H#include<iostream>#include<string>#include<utility>#include<memory>#include<initializer_list>using namespace std;class StrVec{friend bool operator==(const StrVec&,const StrVec&);friend bool operator!=(const StrVec&,const StrVec&);public:    StrVec():elements(nullptr),first_free(nullptr),cap(nullptr){}    StrVec(const StrVec&);    StrVec& operator=(const StrVec&);    ~StrVec() noexcept;    //重载    void push_back(const string&);    void push_back(string&&);    // emplace member covered in chapter 16    template <class... Args> void emplace_back(Args&&...);    size_t size() const { return first_free-elements;}    size_t capacity() const { return cap-elements;}    string *begin() const  {cout<<"begin"<<endl; return elements;}    string *end() const { cout<<"end"<<endl; return first_free;}    void reserve(size_t n);    void resize(size_t n,string s=string());    StrVec(initializer_list<string> il)    {        auto newcapacity=il.size();        auto newdata=alloc.allocate(newcapacity);        auto dest=newdata;        auto elem=il.begin();        while(elem!=il.end())            alloc.construct(dest++,*elem);        elements=newdata;        first_free=cap=dest;    }    StrVec(StrVec &&s) noexcept :elements(s.elements),first_free(s.first_free),cap(s.cap)    {        s.elements=s.first_free=s.cap=nullptr;    }    StrVec& operator=(StrVec &&rhs) noexcept    {        if(this!=&rhs)        {            free();            elements=rhs.elements;            first_free=rhs.first_free;            cap=rhs.cap;            rhs.elements=rhs.first_free=rhs.cap=nullptr;        }        return *this;    }    StrVec& operator=(initializer_list<string>);    string& operator[](size_t n)    {        cout<<"[]"<<endl;        return *(elements+n);    }    const string& operator[](size_t n) const    {        cout<<"const []"<<endl;        return elements[n];    }private:    static allocator<string> alloc;    string *elements;    string *first_free;    string *cap;    void chk_n_alloc()    {        if(size()==capacity()) reallocate();    }    pair<string*,string*> alloc_n_copy(const string*,const string*);    void free();    void reallocate();};bool operator==(const StrVec&,const StrVec&);bool operator!=(const StrVec&,const StrVec&);// emplace member covered in chapter 16template <class... Args>inlinevoid StrVec::emplace_back(Args&&... args){    chk_n_alloc(); // reallocates the StrVec if necessary    alloc.construct(first_free++, std::forward<Args>(args)...);}#endif // STRVEC_H

StrVec.cpp

#include"StrVec.h"#include<algorithm>allocator<string> StrVec::alloc;StrVec::StrVec(const StrVec &s){    auto newdata=alloc_n_copy(s.begin(),s.end());    elements=newdata.first;    first_free=newdata.second;    cap=newdata.second;}StrVec& StrVec::operator=(const StrVec &s){    auto data=alloc_n_copy(s.begin(),s.end());    free();    elements=data.first;    first_free=cap=data.second;    return *this;}StrVec& StrVec::operator=(initializer_list<string> il){    auto data=alloc_n_copy(il.begin(),il.end());    free();    elements=data.first;    first_free=cap=data.second;    return *this;}StrVec::~StrVec() noexcept{    free();}void StrVec::push_back(const string &s){    chk_n_alloc();    alloc.construct(first_free++,s);}void StrVec::push_back(string&& s){    chk_n_alloc();    alloc.construct(first_free++,std::move(s));}pair<string*,string*> StrVec::alloc_n_copy(const string *b, const string *e){    auto data=alloc.allocate(e-b);    return {data,uninitialized_copy(b,e,data)};}void StrVec::free(){    if(elements)    {        //for_each(elements,first_free,[](string p) { alloc.destroy(&p);});        for_each(&elements,&first_free,[](string *p) { alloc.destroy(p);});        //for(auto p=first_free;p!=elements;)          //  alloc.destroy(--p);        alloc.deallocate(elements,cap-elements);    }}void StrVec::reallocate(){    auto newcapacity=size()?2*size():1;    auto newdata=alloc.allocate(newcapacity);    auto dest=newdata;    auto elem=elements;   // auto last=uninitialized_copy(begin(),end(),newdata);   //使用移动迭代器    //auto last=uninitialized_copy(make_move_iterator(begin()),make_move_iterator(end()),newdata);    for(size_t i=0;i!=size();++i)        alloc.construct(dest++,std::move(*elem++));    free();    elements=newdata;    first_free=dest;    cap=elements+newcapacity;}void StrVec::reserve(size_t n){    if(capacity()<n)        reallocate();}void StrVec::resize(size_t n,string s){    if(size()<n)        push_back(s);    else if(size()>n)    {        for(auto p=elements+n;p!=first_free;)            alloc.destroy(p++);        first_free=elements+n;    }}bool operator==(const StrVec& lhs,const StrVec& rhs){    return lhs.elements==rhs.elements&&lhs.first_free==rhs.first_free&&lhs.cap==rhs.cap;}bool operator!=(const StrVec& lhs,const StrVec& rhs){    return !(lhs==rhs);}

main.cpp

#include <iostream>#include"StrVec.h"using namespace std;void print(const StrVec &svec){    cout<<"print"<<endl;    for (auto it : svec)        cout << it << " " ;    cout <<endl;}int main(){    StrVec vec;  // empty StrVec    string s = "some string or another";    vec.push_back(s);      // calls push_back(const string&)    vec.push_back("done"); // calls push_back(string&&)    // emplace member covered in chpater 16    s = "the end";    vec.emplace_back("10"); // adds cccccccccc as a new last element    vec.emplace_back(s);  // uses the string copy constructor    string s1 = "the beginning", s2 = s;    vec.emplace_back(s1 + s2); // uses the move constructor    print(vec);}

16.61定义你自己版本的make_shared。

#include<iostream>#include<memory>#include<string>using namespace std;template <typename T,typename... Args>shared_ptr<T>Make_shared(Args&&... args){   return make_shared<T>(std::forward<Args>(args)...);}int main(){    auto p=Make_shared<int>(1);    cout<<*p<<endl;    auto pp=Make_shared<string>(10,c);    cout<<*pp<<endl;}

 

转发参数包的例子