转发参数包的例子

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 16

template <class... Args>

inline

void 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;

}

 

你可能感兴趣的:(例子)