转发参数包的例子

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

 

上一篇:【译】SQL Server索引进阶第八篇:唯一索引


下一篇:【译】SQL Server索引进阶第四篇:页和区