14.2
#include<string>
#include<iostream>
struct Sales_data;
std::istream& operator>>(std::istream& is, Sales_data& item);
std::ostream& operator<<(std::ostream& os, const Sales_data& item);
Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs);
class Sales_data
{
friend std::istream &operator>>(std::istream&, Sales_data&);
friend std::ostream &operator<<(std::ostream&, Sales_data&);
friend Sales_data operator+(const Sales_data&, const Sales_data&);
public:
Sales_data(const std::string& s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(p* n)
{ std::cout << "Sales_data(const std::string& s, unsigned n, double p)" << std::endl; }
Sales_data() :Sales_data("", 0, 0)
{ std::cout << "Sales_data() :Sales_data("", 0, 0)" << std::endl; }
Sales_data(const std::string& s) :Sales_data(s, 0, 0)
{ std::cout << "Sales_data(const std::string& s):Sales_data(s, 0, 0)" << std::endl; }
Sales_data(std::istream& is) :Sales_data()
{ is >> *this; std::cout << "Sales_data(std::istream& is) :Sales_data() " << std::endl; }
std::string isbn() const { return bookNo; }
Sales_data& operator+=(const Sales_data&);
private:
inline double avg_price()const;
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
inline double Sales_data::avg_price()const
{
if (units_sold)
return revenue / units_sold;
else
return 0;
}
Sales_data& Sales_data::operator+=(const Sales_data& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
std::istream& operator>>(std::istream& is, Sales_data& item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
if (is)
item.revenue = price * item.units_sold;
else
item = Sales_data();
return is;
}
std::ostream& operator<<(std::ostream& os, Sales_data& item)
{
os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
return os;
}
Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs)
{
Sales_data sum = lhs;
sum += rhs;
return sum;
}
int main()
{
Sales_data sales_data1("12313", 2, 5);
Sales_data sales_data2;
Sales_data sales_data3("12135");
Sales_data sale_data4(std::cin);
return 0;
}
14.5
aaa.h
#ifndef CP5_CH14_EX14_05_H
#define CP5_CH14_EX14_05_H
#include <iostream>
#include <string>
class Book {
friend std::istream& operator>>(std::istream&, Book&);
friend std::ostream& operator<<(std::ostream&, const Book&);
friend bool operator==(const Book&, const Book&);
friend bool operator!=(const Book&, const Book&);
public:
Book() = default;
Book(unsigned no, std::string name, std::string author, std::string pubdate)
:no_(no),name_(name),author_(author),pubdate_(pubdate) {}
Book(std::istream& in) { in >> *this; }
private:
unsigned no_;
std::string name_;
std::string author_;
std::string pubdate_;
};
std::istream& operator>>(std::istream&, Book&);
std::ostream& operator<<(std::ostream&, const Book&);
bool operator==(const Book&, const Book&);
bool operator!=(const Book&, const Book&);
#endif // CP5_CH14_EX14_05_H
aaa.cpp
#include"aaa.h"
std::istream& operator>>(std::istream&in, Book&book)
{
in >> book.no_ >> book.name_ >> book.author_ >> book.pubdate_;
return in;
}
std::ostream& operator<<(std::ostream&out, const Book&book)
{
out << book.no_ << book.name_ << book.author_ << book.pubdate_;
return out;
}
bool operator==(const Book& lhs, const Book& rhs)
{
return lhs.no_ == rhs.no_;
}
bool operator!=(const Book&lhs, const Book&rhs)
{
return!(lhs == rhs);
}
main
#include"aaa.h"
int main()
{
Book book1{ 123,"az","jack","2020" };
Book book2{ 123,"sa","jack","2021" };
if (book1 == book2)
{
std::cout << book1 << std::endl;
}
return 0;
}
14.7
ostream &operator<<(ostream &os,const string &s)
{
for(auto iter =s.elements;it!=s.first_free;++it)
{
os<<*iter;
}
return os;
}
14.9
istream &operator>>(istream &is,Sales_data &iteam)
{
double price;
is>>item.bookNo>>item.units_sold>>price;
if(is)
{
item.revenue = item.units_sold*price;
}
else
{
item =Sales_data();
}
return is;
}
14.19
#include <iostream>
#include <string>
class Book {
friend std::istream& operator>>(std::istream&, Book&);
friend std::ostream& operator<<(std::ostream&, const Book&);
friend bool operator==(const Book&, const Book&);
friend bool operator!=(const Book&, const Book&);
friend bool operator<(const Book&, const Book&);
friend bool operator>(const Book&, const Book&);
friend bool operator<=(const Book&, const Book&);
friend bool operator>=(const Book&, const Book&);
public:
Book() = default;
Book(unsigned no, std::string name, std::string author, std::string pubdate) :no_(no), name_(name), author_(author), pubdate_(pubdate) { }
Book(std::istream& in) { in >> *this; }
private:
unsigned int no_;
std::string name_;
std::string author_;
std::string pubdate_;
};
std::istream& operator>>(std::istream& in, Book& book)
{
in >> book.no_ >> book.name_ >> book.author_ >> book.pubdate_;
return in;
}
std::ostream& operator<<(std::ostream& out, const Book& book)
{
out << book.no_ << " " << book.name_ << " " << book.author_ << " " << book.pubdate_;
return out;
}
bool operator==(const Book& lhs, const Book& rhs)
{
return lhs.no_ == rhs.no_;
}
bool operator!=(const Book& lhs, const Book& rhs)
{
return !(lhs == rhs);
}
bool operator<(const Book& lhs, const Book& rhs)
{
return lhs.no_ < rhs.no_;
}
bool operator>(const Book& lhs, const Book& rhs)
{
return rhs < lhs;
}
bool operator<=(const Book& lhs, const Book& rhs)
{
return !(rhs < lhs);
}
bool operator>=(const Book& lhs, const Book& rhs)
{
return !(lhs < rhs);
}
int main()
{
Book book1(123, "CP5", "Lippman", "2012");
Book book2(123, "CP5", "Lippman", "2012");
if (book1 == book2)
std::cout << book1 << std::endl;
}
14.20
Sales_data& Sales_data::operator+(const Sales_data &rhs)
{
Sales_data old_data = *this;
*this = old_data + rhs;
return *this;
}
Sales_data operator+=(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum;
sum.units_sold = lhs.units_sold + rhs.units_sold;
sum.revenue = lhs.revenue + rhs.revenue;
return sum;
}
14.21
本题的+和+=都用到了临时变量;
14.22
#include<iostream>
#include <string>
struct Sales_data;
std::istream& operator>>(std::istream& is, Sales_data& item);
std::ostream& operator<<(std::ostream& os, const Sales_data& item);
Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs);
struct Sales_data
{
friend std::istream& operator>>(std::istream&, Sales_data&);
friend std::ostream& operator<<(std::ostream&, const Sales_data&);
friend Sales_data operator+(const Sales_data&, const Sales_data&);
public:
Sales_data(const std::string& s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p* n) { std::cout << "Sales_data(const std::string &s, unsigned n, double p)" << std::endl; }
Sales_data() : Sales_data("", 0, 0) { std::cout << "Sales_data() : Sales_data(\"\", 0, 0)" << std::endl; }
Sales_data(const std::string& s) : Sales_data(s, 0, 0) { std::cout << "Sales_data(const std::string &s) : Sales_data" << std::endl; }
Sales_data(std::istream& is) : Sales_data() {/*read(is, *this);*/ is >> *this; std::cout << "Sales_data(std::istream &is) : Sales_data()" << std::endl; }
std::string isbn() const { return bookNo; }
Sales_data& operator=(const std::string&);
Sales_data& operator+=(const Sales_data&);
Sales_data& operator-=(const Sales_data&);
private:
inline double avg_price() const;
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
inline double Sales_data::avg_price() const
{
if (units_sold)
return revenue / units_sold;
else
return 0;
}
Sales_data& Sales_data::operator=(const std::string& s)
{
*this = Sales_data(s);
return *this;
}
Sales_data& Sales_data::operator+=(const Sales_data& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
Sales_data& Sales_data::operator-=(const Sales_data& rhs)
{
units_sold -= rhs.units_sold;
revenue -= rhs.revenue;
return *this;
}
std::istream& operator>>(std::istream& is, Sales_data& item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
if (is)
item.revenue = price * item.units_sold;
else
item = Sales_data();
return is;
}
std::ostream& operator<<(std::ostream& os, const Sales_data& item)
{
os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
return os;
}
Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs)
{
Sales_data sum = lhs;
sum += rhs;
return sum;
}
int main()
{
return 0;
}
14.23
#include <string>
#include <utility>
#include <memory>
#include <algorithm>
class StrVec
{
friend bool operator==(StrVec& lhs, StrVec& rhs);
friend bool operator!=(StrVec& lhs, StrVec& rhs);
friend bool operator<(StrVec& lhs, StrVec& rhs);
friend bool operator>(StrVec& lhs, StrVec& rhs);
friend bool operator<=(StrVec& lhs, StrVec& rhs);
friend bool operator>=(StrVec& lhs, StrVec& rhs);
public:
StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { }
StrVec(std::initializer_list<std::string>);
StrVec(const StrVec&);
StrVec(StrVec&& s) noexcept : alloc(std::move(s.alloc)), elements(std::move(s.elements)), first_free(std::move(s.first_free)), cap(std::move(s.cap)) { s.elements = s.first_free = s.cap = nullptr; }
StrVec& operator=(const StrVec&);
StrVec& operator=(StrVec&&) noexcept;
StrVec& operator=(std::initializer_list<std::string>);
~StrVec();
void push_back(const std::string&);
size_t size() const { return first_free - elements; }
size_t capacity() const { return cap - elements; }
std::string* begin() const { return elements; }
std::string* end() const { return first_free; }
void reserve(size_t n);
void resize(size_t n);
void resize(size_t n, const std::string& s);
private:
std::allocator<std::string> alloc;
void chk_n_alloc() { if (size() == capacity()) reallocate(); }
std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);
void free();
void reallocate();
std::string* elements;
std::string* first_free;
std::string* cap;
};
StrVec::StrVec(std::initializer_list<std::string> il)
{
auto newdata = alloc_n_copy(il.begin(), il.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
void StrVec::push_back(const std::string& s)
{
chk_n_alloc();
alloc.construct(first_free++, s);
}
std::pair<std::string*, std::string*> StrVec::alloc_n_copy(const std::string* b, const std::string* e)
{
auto data = alloc.allocate(e - b);
return { data, uninitialized_copy(b, e, data) };
}
void StrVec::free()
{
if (elements)
{
std::for_each(elements, first_free, [this](std::string& p) { alloc.destroy(&p); });
// for(auto p = first_free; p != elements; )
// alloc.destroy(--p);
alloc.deallocate(elements, cap - elements);
}
}
StrVec::StrVec(const StrVec& s)
{
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
StrVec& StrVec::operator=(std::initializer_list<std::string> il)
{
auto data = alloc_n_copy(il.begin(), il.end());
free();
elements = data.first;
first_free = cap = data.second;
return *this;
}
StrVec::~StrVec()
{
free();
}
void StrVec::reserve(size_t n)
{
if (n <= capacity()) return;
auto newdata = alloc.allocate(n);
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, std::move(*elem++));
free();
elements = newdata;
first_free = dest;
cap = elements + n;
}
void StrVec::resize(size_t n)
{
resize(n, std::string());
}
void StrVec::resize(size_t n, const std::string& s)
{
if (n < size())
{
while (n < size())
alloc.destroy(--first_free);
}
else if (n > size())
{
while (n > size())
push_back(s);
// alloc.construct(first_free, s);
}
}
StrVec& StrVec::operator=(const StrVec& rhs)
{
auto data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = data.second;
return *this;
}
StrVec& StrVec::operator=(StrVec&& rhs) noexcept
{
if (this != &rhs)
{
free();
alloc = std::move(rhs.alloc);
elements = std::move(rhs.elements);
first_free = std::move(rhs.first_free);
cap = std::move(rhs.cap);
rhs.elements = rhs.first_free = rhs.cap = nullptr;
}
return *this;
}
void StrVec::reallocate()
{
auto newcapacity = size() ? 2 * size() : 1;
auto newdata = alloc.allocate(newcapacity);
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, std::move(*elem++));
free();
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
}
bool operator==(StrVec& lhs, StrVec& rhs)
{
return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
bool operator!=(StrVec& lhs, StrVec& rhs)
{
return !(lhs == rhs);
}
bool operator<(StrVec& lhs, StrVec& rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
bool operator>(StrVec& lhs, StrVec& rhs)
{
return rhs < lhs;
}
bool operator<=(StrVec& lhs, StrVec& rhs)
{
return !(rhs < lhs);
}
bool operator>=(StrVec& lhs, StrVec& rhs)
{
return !(lhs < rhs);
}
int main()
{
StrVec s({ "aaa","bbb" });
return 0;
}
14.25
#include <iostream>
#include <string>
class Book {
friend std::istream& operator>>(std::istream&, Book&);
friend std::ostream& operator<<(std::ostream&, const Book&);
friend bool operator==(const Book&, const Book&);
friend bool operator!=(const Book&, const Book&);
friend bool operator<(const Book&, const Book&);
friend bool operator>(const Book&, const Book&);
friend bool operator<=(const Book&, const Book&);
friend bool operator>=(const Book&, const Book&);
public:
Book() = default;
Book(unsigned no, std::string name, std::string author, std::string pubdate) :no_(no), name_(name), author_(author), pubdate_(pubdate) { }
Book(std::istream& in) { in >> *this; }
//拷贝赋值
Book& operator=(const Book&);
//移动赋值
Book& operator=(const Book&&)noexcept;
private:
unsigned int no_;
std::string name_;
std::string author_;
std::string pubdate_;
};
Book& Book::operator=(const Book& rhs)
{
this->no_ = rhs.no_;
this->name_ = rhs.name_;
this->author_ = rhs.author_;
this->pubdate_ = rhs.pubdate_;
return *this;
}
Book& Book::operator=(const Book&& rhs)noexcept
{
if(this!=&rhs)
{
this->no_ = rhs.no_;
this->name_ = rhs.name_;
this->author_ = rhs.author_;
this->pubdate_ = rhs.pubdate_;
}
return* this;
}
std::istream& operator>>(std::istream& in, Book& book)
{
in >> book.no_ >> book.name_ >> book.author_ >> book.pubdate_;
return in;
}
std::ostream& operator<<(std::ostream& out, const Book& book)
{
out << book.no_ << " " << book.name_ << " " << book.author_ << " " << book.pubdate_;
return out;
}
bool operator==(const Book& lhs, const Book& rhs)
{
return lhs.no_ == rhs.no_;
}
bool operator!=(const Book& lhs, const Book& rhs)
{
return !(lhs == rhs);
}
bool operator<(const Book& lhs, const Book& rhs)
{
return lhs.no_ < rhs.no_;
}
bool operator>(const Book& lhs, const Book& rhs)
{
return rhs < lhs;
}
bool operator<=(const Book& lhs, const Book& rhs)
{
return !(rhs < lhs);
}
bool operator>=(const Book& lhs, const Book& rhs)
{
return !(lhs < rhs);
}
int main()
{
Book book1(123, "CP5", "Lippman", "2012");
Book book2(123, "CP5", "Lippman", "2012");
if (book1 == book2)
std::cout << book1 << std::endl;
}
14.26
StrBlob、StrBlobPtr
#include<iostream>
#include <string>
#include <initializer_list>
#include <memory>
#include <vector>
#include <stdexcept>
class ConstStrBlobPtr;
class StrBlob
{
friend class ConstStrBlobPtr;
friend bool operator==(const StrBlob& lhs, const StrBlob& rhs);
friend bool operator!=(const StrBlob& lhs, const StrBlob& rhs);
friend bool operator<(const StrBlob& lhs, const StrBlob& rhs);
friend bool operator>(const StrBlob& lhs, const StrBlob& rhs);
friend bool operator<=(const StrBlob& lhs, const StrBlob& rhs);
friend bool operator>=(const StrBlob& lhs, const StrBlob& rhs);
public:
typedef std::vector<std::string>::size_type size_type;
StrBlob();
StrBlob(std::initializer_list<std::string> il);
StrBlob(const StrBlob&);
StrBlob& operator=(const StrBlob&);
size_type size() const { return data->size(); }
bool empty() const { return data->empty(); }
void push_back(const std::string& t) { data->push_back(t); }
void push_back(std::string&& t) { data->push_back(t); }
void pop_back();
std::string& front();
std::string& back();
const std::string& front() const;
const std::string& back() const;
ConstStrBlobPtr begin();
ConstStrBlobPtr end();
std::string& operator[](size_t n) { return ( * data)[n]; }
const std::string& operator[](size_t n) const { return (*data)[n]; }
private:
std::shared_ptr<std::vector<std::string>> data;
void check(size_type i, const std::string& msg) const;
};
class ConstStrBlobPtr
{
friend bool operator==(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs);
friend bool operator!=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs);
public:
ConstStrBlobPtr() : curr(0) {};
ConstStrBlobPtr(const StrBlob& a, size_t sz = 0) : wptr(a.data), curr(sz) {}
std::string& deref() const;
ConstStrBlobPtr& incr();
private:
std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) const;
std::weak_ptr<std::vector<std::string>> wptr;
std::size_t curr;
};
std::shared_ptr<std::vector<std::string>> ConstStrBlobPtr::check(std::size_t i, const std::string& msg) const
{
auto ret = wptr.lock();
if (!ret)
throw std::runtime_error("unbound ConstStrBlobPtr");
if (i >= ret->size())
throw std::out_of_range(msg);
return ret;
}
std::string& ConstStrBlobPtr::deref() const
{
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
ConstStrBlobPtr& ConstStrBlobPtr::incr()
{
check(curr, "increment past end of ConstStrBlobPtr");
++curr;
return *this;
}
StrBlob::StrBlob() : data(std::make_shared<std::vector<std::string>>()) {}
StrBlob::StrBlob(std::initializer_list<std::string> il) : data(std::make_shared<std::vector<std::string>>(il)) {}
StrBlob::StrBlob(const StrBlob& sb) { data = std::make_shared<std::vector<std::string>>(*sb.data); }
StrBlob& StrBlob::operator=(const StrBlob& sb) { data = std::make_shared<std::vector<std::string>>(*sb.data); return *this; }
void StrBlob::check(size_type i, const std::string& msg) const
{
if (i >= data->size())
throw std::out_of_range(msg);
}
std::string& StrBlob::front()
{
check(0, "front on empty StrBlob");
return data->front();
}
std::string& StrBlob::back()
{
check(0, "back on empty StrBlob");
return data->back();
}
const std::string& StrBlob::front() const
{
check(0, "front on empty StrBlob");
return data->front();
}
const std::string& StrBlob::back() const
{
check(0, "back on empty StrBlob");
return data->back();
}
void StrBlob::pop_back()
{
check(0, "pop_back on empty StrBlob");
data->pop_back();
}
ConstStrBlobPtr StrBlob::begin() { return ConstStrBlobPtr(*this); }
ConstStrBlobPtr StrBlob::end()
{
auto ret = ConstStrBlobPtr(*this, data->size());
return ret;
}
bool operator==(const StrBlob& lhs, const StrBlob& rhs)
{
return *lhs.data == *rhs.data;
}
bool operator!=(const StrBlob& lhs, const StrBlob& rhs)
{
return !(lhs == rhs);
}
bool operator<(const StrBlob& lhs, const StrBlob& rhs)
{
return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), rhs.data->end());
}
bool operator>(const StrBlob& lhs, const StrBlob& rhs)
{
return rhs < lhs;
}
bool operator<=(const StrBlob& lhs, const StrBlob& rhs)
{
return !(rhs < lhs);
}
bool operator>=(const StrBlob& lhs, const StrBlob& rhs)
{
return !(lhs < rhs);
}
bool operator==(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
auto lret = lhs.wptr.lock(), rret = rhs.wptr.lock();
return lret == rret && lhs.curr == rhs.curr;
}
bool operator!=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
return !(lhs == rhs);
}
int main()
{
StrBlob b1 = { "a","aa","aaa" };
StrBlob b2 = b1;
return 0;
}
StrVec类
#include <string>
#include <utility>
#include <memory>
#include <algorithm>
class StrVec
{
friend bool operator==(StrVec& lhs, StrVec& rhs);
friend bool operator!=(StrVec& lhs, StrVec& rhs);
friend bool operator<(StrVec& lhs, StrVec& rhs);
friend bool operator>(StrVec& lhs, StrVec& rhs);
friend bool operator<=(StrVec& lhs, StrVec& rhs);
friend bool operator>=(StrVec& lhs, StrVec& rhs);
public:
StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { }
StrVec(std::initializer_list<std::string>);
StrVec(const StrVec&);
StrVec(StrVec&& s) noexcept : alloc(std::move(s.alloc)), elements(std::move(s.elements)), first_free(std::move(s.first_free)), cap(std::move(s.cap)) { s.elements = s.first_free = s.cap = nullptr; }
StrVec& operator=(const StrVec&);
StrVec& operator=(StrVec&&) noexcept;
std::string& operator[](std::size_t n) { return elements[n]; }
const std::string& operator[](std::size_t n)const { return elements[n]; }
~StrVec();
void push_back(const std::string&);
size_t size() const { return first_free - elements; }
size_t capacity() const { return cap - elements; }
std::string* begin() const { return elements; }
std::string* end() const { return first_free; }
void reserve(size_t n);
void resize(size_t n);
void resize(size_t n, const std::string& s);
private:
std::allocator<std::string> alloc;
void chk_n_alloc() { if (size() == capacity()) reallocate(); }
std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*);
void free();
void reallocate();
std::string* elements;
std::string* first_free;
std::string* cap;
};
StrVec::StrVec(std::initializer_list<std::string> il)
{
auto newdata = alloc_n_copy(il.begin(), il.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
void StrVec::push_back(const std::string& s)
{
chk_n_alloc();
alloc.construct(first_free++, s);
}
std::pair<std::string*, std::string*> StrVec::alloc_n_copy(const std::string* b, const std::string* e)
{
auto data = alloc.allocate(e - b);
return { data, uninitialized_copy(b, e, data) };
}
void StrVec::free()
{
if (elements)
{
std::for_each(elements, first_free, [this](std::string& p) { alloc.destroy(&p); });
// for(auto p = first_free; p != elements; )
// alloc.destroy(--p);
alloc.deallocate(elements, cap - elements);
}
}
StrVec::StrVec(const StrVec& s)
{
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
StrVec::~StrVec()
{
free();
}
void StrVec::reserve(size_t n)
{
if (n <= capacity()) return;
auto newdata = alloc.allocate(n);
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, std::move(*elem++));
free();
elements = newdata;
first_free = dest;
cap = elements + n;
}
void StrVec::resize(size_t n)
{
resize(n, std::string());
}
void StrVec::resize(size_t n, const std::string& s)
{
if (n < size())
{
while (n < size())
alloc.destroy(--first_free);
}
else if (n > size())
{
while (n > size())
push_back(s);
// alloc.construct(first_free, s);
}
}
StrVec& StrVec::operator=(const StrVec& rhs)
{
auto data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = data.second;
return *this;
}
StrVec& StrVec::operator=(StrVec&& rhs) noexcept
{
if (this != &rhs)
{
free();
alloc = std::move(rhs.alloc);
elements = std::move(rhs.elements);
first_free = std::move(rhs.first_free);
cap = std::move(rhs.cap);
rhs.elements = rhs.first_free = rhs.cap = nullptr;
}
return *this;
}
void StrVec::reallocate()
{
auto newcapacity = size() ? 2 * size() : 1;
auto newdata = alloc.allocate(newcapacity);
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, std::move(*elem++));
free();
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
}
bool operator==(StrVec& lhs, StrVec& rhs)
{
return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
bool operator!=(StrVec& lhs, StrVec& rhs)
{
return !(lhs == rhs);
}
bool operator<(StrVec& lhs, StrVec& rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
bool operator>(StrVec& lhs, StrVec& rhs)
{
return rhs < lhs;
}
bool operator<=(StrVec& lhs, StrVec& rhs)
{
return !(rhs < lhs);
}
bool operator>=(StrVec& lhs, StrVec& rhs)
{
return !(lhs < rhs);
}
int main()
{
StrVec s({ "aaa","bbb" });
return 0;
}
String 类
#include<iostream>
#include <memory>
#include <algorithm>
#include <cstring>
#include <iostream>
#include<vector>
class String
{
friend std::ostream& operator<<(std::ostream& os, const String& s);
friend bool operator==(const String& lhs, const String& rhs);
friend bool operator!=(const String& lhs, const String& rhs);
friend bool operator<(const String& lhs, const String& rhs);
friend bool operator>(const String& lhs, const String& rhs);
friend bool operator<=(const String& lhs, const String& rhs);
friend bool operator>=(const String& lhs, const String& rhs);
public:
String();
String(const char*);
String(const String&);
String(String&&) noexcept;
String& operator=(const String&);
String& operator=(String&&) noexcept;
char* begin() const { return elements; }
char* end() const { return first_free; }
~String();
private:
std::pair<char*, char*> alloc_n_copy(const char*, const char*);
void free();
std::allocator<char> alloc;
char* elements;
char* first_free;
};
std::pair<char*, char*> String::alloc_n_copy(const char* begin, const char* end)
{
char* p = alloc.allocate(end - begin);
return{ p, std::uninitialized_copy(begin, end, p) };
}
String::String(const char* cp)
{
size_t n = strlen(cp);
auto newstr = alloc_n_copy(cp, cp + n);
elements = newstr.first;
first_free = newstr.second;
}
String::String()
{
String("");
}
String::String(const String& rhs)
{
auto newstr = alloc_n_copy(rhs.begin(), rhs.end());
elements = newstr.first;
first_free = newstr.second;
std::cout << "String(const String &rhs)" << std::endl;
}
String::String(String&& s) noexcept : alloc(std::move(s.alloc)), elements(std::move(s.elements)), first_free(std::move(s.first_free))
{
std::cout << "String::String(String &&s) noexcept" << std::endl;
s.elements = s.first_free = nullptr;
}
void String::free()
{
if (elements)
{
std::for_each(elements, first_free, [this](char cp) { alloc.destroy(&cp); });
alloc.deallocate(elements, first_free - elements);
}
}
String& String::operator=(const String& rhs)
{
auto newstr = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = newstr.first;
first_free = newstr.second;
std::cout << "String& operator=(const String& rhs)" << std::endl;
return *this;
}
String& String::operator=(String&& rhs) noexcept
{
std::cout << "String& String::operator=(String &&rhs) noexcept" << std::endl;
if (&rhs != this)
{
free();
alloc = std::move(rhs.alloc);
elements = std::move(rhs.elements);
first_free = std::move(rhs.first_free);
rhs.elements = rhs.first_free = nullptr;
}
return *this;
}
String::~String()
{
free();
}
std::ostream& operator<<(std::ostream& os, const String& s)
{
for (auto iter = s.elements; iter != s.first_free; ++iter)
{
os << *iter;
}
return os;
}
bool operator==(const String& lhs, const String& rhs)
{
return (lhs.first_free - lhs.elements) == (rhs.first_free - rhs.elements) && std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
bool operator !=(const String& lhs, const String& rhs)
{
return!(lhs == rhs);
}
bool operator<(const String& lhs, const String& rhs)
{
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
bool operator>(const String& lhs, const String& rhs)
{
return rhs<lhs;
}
bool operator<=(const String& lhs, const String& rhs)
{
return !(rhs < lhs);
}
bool operator>=(const String& lhs, const String& rhs)
{
return (lhs<rhs);
}
int main()
{
std::vector<String>v;
v.push_back("aaa");
v.push_back("bbb");
std::cout << v[1] << std::endl;
return 0;
}
14.30
#include<iostream>
#include <string>
#include <initializer_list>
#include <memory>
#include <vector>
#include <stdexcept>
class ConstStrBlobPtr;
class StrBlob
{
friend class ConstStrBlobPtr;
friend bool operator==(const StrBlob& lhs, const StrBlob& rhs);
friend bool operator!=(const StrBlob& lhs, const StrBlob& rhs);
friend bool operator<(const StrBlob& lhs, const StrBlob& rhs);
friend bool operator>(const StrBlob& lhs, const StrBlob& rhs);
friend bool operator<=(const StrBlob& lhs, const StrBlob& rhs);
friend bool operator>=(const StrBlob& lhs, const StrBlob& rhs);
public:
typedef std::vector<std::string>::size_type size_type;
StrBlob();
StrBlob(std::initializer_list<std::string> il);
StrBlob(const StrBlob&);
StrBlob& operator=(const StrBlob&);
size_type size() const { return data->size(); }
bool empty() const { return data->empty(); }
void push_back(const std::string& t) { data->push_back(t); }
void push_back(std::string&& t) { data->push_back(t); }
void pop_back();
std::string& front();
std::string& back();
const std::string& front() const;
const std::string& back() const;
ConstStrBlobPtr begin();
ConstStrBlobPtr end();
std::string& operator[](size_t n) { return (*data)[n]; }
const std::string& operator[](size_t n) const { return (*data)[n]; }
private:
std::shared_ptr<std::vector<std::string>> data;
void check(size_type i, const std::string& msg) const;
};
class ConstStrBlobPtr
{
friend bool operator==(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs);
friend bool operator!=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs);
public:
ConstStrBlobPtr() : curr(0) {};
ConstStrBlobPtr(const StrBlob& a, size_t sz = 0) : wptr(a.data), curr(sz) {}
std::string& deref() const;
ConstStrBlobPtr& incr();
ConstStrBlobPtr& operator++();
ConstStrBlobPtr& operator--();
ConstStrBlobPtr operator++(int);
ConstStrBlobPtr operator--(int);
const std::string& operator*()const
{
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
const std::string* operator->()const
{
return &this->operator*();
}
private:
std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) const;
std::weak_ptr<std::vector<std::string>> wptr;
std::size_t curr;
};
std::shared_ptr<std::vector<std::string>> ConstStrBlobPtr::check(std::size_t i, const std::string& msg) const
{
auto ret = wptr.lock();
if (!ret)
throw std::runtime_error("unbound ConstStrBlobPtr");
if (i >= ret->size())
throw std::out_of_range(msg);
return ret;
}
std::string& ConstStrBlobPtr::deref() const
{
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
ConstStrBlobPtr& ConstStrBlobPtr::incr()
{
check(curr, "increment past end of ConstStrBlobPtr");
++curr;
return *this;
}
ConstStrBlobPtr& ConstStrBlobPtr::operator++()
{
check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
ConstStrBlobPtr& ConstStrBlobPtr::operator--()
{
--curr;
check(curr, "decrement past begin of StrBlobPtr");
return *this;
}
ConstStrBlobPtr ConstStrBlobPtr::operator++(int)
{
ConstStrBlobPtr ret = *this;
++* this;
return ret;
}
ConstStrBlobPtr ConstStrBlobPtr::operator--(int)
{
ConstStrBlobPtr ret = *this;
--* this;
return ret;
}
StrBlob::StrBlob() : data(std::make_shared<std::vector<std::string>>()) {}
StrBlob::StrBlob(std::initializer_list<std::string> il) : data(std::make_shared<std::vector<std::string>>(il)) {}
StrBlob::StrBlob(const StrBlob& sb) { data = std::make_shared<std::vector<std::string>>(*sb.data); }
StrBlob& StrBlob::operator=(const StrBlob& sb) { data = std::make_shared<std::vector<std::string>>(*sb.data); return *this; }
void StrBlob::check(size_type i, const std::string& msg) const
{
if (i >= data->size())
throw std::out_of_range(msg);
}
std::string& StrBlob::front()
{
check(0, "front on empty StrBlob");
return data->front();
}
std::string& StrBlob::back()
{
check(0, "back on empty StrBlob");
return data->back();
}
const std::string& StrBlob::front() const
{
check(0, "front on empty StrBlob");
return data->front();
}
const std::string& StrBlob::back() const
{
check(0, "back on empty StrBlob");
return data->back();
}
void StrBlob::pop_back()
{
check(0, "pop_back on empty StrBlob");
data->pop_back();
}
ConstStrBlobPtr StrBlob::begin() { return ConstStrBlobPtr(*this); }
ConstStrBlobPtr StrBlob::end()
{
auto ret = ConstStrBlobPtr(*this, data->size());
return ret;
}
bool operator==(const StrBlob& lhs, const StrBlob& rhs)
{
return *lhs.data == *rhs.data;
}
bool operator!=(const StrBlob& lhs, const StrBlob& rhs)
{
return !(lhs == rhs);
}
bool operator<(const StrBlob& lhs, const StrBlob& rhs)
{
return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), rhs.data->end());
}
bool operator>(const StrBlob& lhs, const StrBlob& rhs)
{
return rhs < lhs;
}
bool operator<=(const StrBlob& lhs, const StrBlob& rhs)
{
return !(rhs < lhs);
}
bool operator>=(const StrBlob& lhs, const StrBlob& rhs)
{
return !(lhs < rhs);
}
bool operator==(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
auto lret = lhs.wptr.lock(), rret = rhs.wptr.lock();
return lret == rret && lhs.curr == rhs.curr;
}
bool operator!=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs)
{
return !(lhs == rhs);
}
int main()
{
StrBlob b1 = { "a","aa","aaa" };
StrBlob b2 = b1;
return 0;
}
14.32
class Myclass
{
public:
std::string * operator->()const
{
return ptr->operator->();
}
private:
StrBlobPtr *ptr;
};
14.34
#include<iostream>
#include<string>
class if_then_else
{
public:
std::string operator()(bool b, std::string first_result, std::string second_result)
{
return b ? first_result : second_result;
}
};
int main()
{
if_then_else if_object;
std::cout << if_object(true, "a", "b") << std::endl;
return 0;
}
14.35
#include<iostream>
#include<string>
#include<vector>
using std::string;
class ReadString
{
public:
ReadString(std::istream& i = std::cin) :is(i) {}
string operator()()
{
std::string s;
std::getline(is, s);
return s;
}
private:
std::istream& is;
};
int main()
{
std::vector<string>vs;
string new_string;
ReadString ReadObject;
do
{
new_string = ReadObject();
vs.push_back(new_string);
} while (!new_string.empty());
for (auto s : vs)
std::cout << s << " ";
std::cout << std::endl;
return 0;
}
14.37
#include<string>
#include<iostream>
#include<vector>
#include<algorithm>
class equal_int
{
public:
equal_int(int i) :default_number(i) {}
bool operator()(int ele) { return default_number ==ele; }
private:
int default_number;
};
int main()
{
std::vector<int >vi = { 1,2,3,4,5,6 };
std::replace_if(vi.begin(), vi.end(), equal_int(3), 5);
for (auto i : vi)
std::cout << i << " ";
std::cout << std::endl;
return 0;
}
14.38
#include<iostream>
#include<fstream>
#include<vector>
#include<string>
class CompareString
{
public:
CompareString(size_t n) :default_size(n) {}
bool operator()(const std::string& s)const
{
return default_size == s.size();
}
private:
size_t default_size;
};
int main()
{
std::ifstream ifs("letter.txt");
if (!ifs) return -1;
std::vector<std::string>vs;
for (std::string curr; ifs >> curr; vs.push_back(curr));
for (int i = 1, n = 0; i < 11; ++i)
{
for (auto iter = vs.begin(); iter != vs.end();)
{
iter = std::find_if(iter + 1, vs.end(), CompareString(i));
if (iter != vs.end())++n;
}
std::cout << "length:" << i << " " << n << std::endl;
n = 0;
}
return 0;
}
14.39
#include<iostream>
#include<fstream>
#include<vector>
#include<string>
class CompareString
{
public:
CompareString(size_t n) :default_size(n) {}
bool operator()(const std::string& s)const
{
return default_size == s.size();
}
private:
size_t default_size;
};
int main()
{
std::ifstream ifs("letter.txt");
if (!ifs) return -1;
std::vector<std::string>vs;
for (std::string curr; ifs >> curr; vs.push_back(curr));
int n = 0;
for (int i = 1; i < 10; ++i)
{
for (auto iter = vs.begin(); iter != vs.end();)
{
iter = std::find_if(iter + 1, vs.end(), CompareString(i));
if (iter != vs.end())++n;
}
}
std::cout << "length 1-9:" << " " << n << std::endl;
n = 0;
for (int i = 10; i < 100; ++i)
{
for (auto iter = vs.begin(); iter != vs.end();)
{
iter = std::find_if(iter + 1, vs.end(), CompareString(i));
if (iter != vs.end())++n;
}
}
std::cout << "length 10-99:" << " " << n << std::endl;
return 0;
}
14.40
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
class bigger
{
public:
bigger(vector<string>::size_type i) :default_num(i) {}
bool operator()(const string& s)
{
return s.size() >= default_num;
}
private:
vector<string>::size_type default_num;
};
class str_compare
{
public:
bool operator()(const string& lhs, const string& rhs)
{
return lhs.size() < rhs.size();
}
};
vector<string>& elimDups(vector<string>& words)
{
sort(words.begin(), words.end());
auto end_unique = unique(words.begin(), words.end());
words.erase(end_unique, words.end());
return words;
}
void biggies(vector<string>& words, vector<string>::size_type sz)
{
elimDups(words);
stable_sort(words.begin(), words.end(), str_compare());
auto wc = find_if(words.begin(), words.end(), bigger(sz));
auto count = words.end() - wc;
cout << count << endl;
for (auto s : words)
cout << s << " ";
cout << endl;
}
int main()
{
vector<string>vs = { "b","a","c","a","b","d","asdasdas","sa","sadsafsaf" };
biggies(vs, 5);
return 0;
}
14.41
当函数使用次数少且实现简单时,使用lambda;
14.42
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<functional>
int main()
{
std::vector<int >v1 = { 1,1024,1025,1,1026 };
std::cout << std::count_if(v1.begin(), v1.end(), std::bind(std::greater<int>(), std::placeholders::_1, 1024)) << std::endl;
std::vector<std::string>vs = { "pooh","hi","hello" };
std::cout << *(std::find_if(vs.begin(), vs.end(), std::bind(std::not_equal_to<std::string>(), std::placeholders::_1, "pooh"))) << std::endl;
std::vector<int>v2 = { 1,2,3,4,5 };
std::transform(v2.begin(), v2.end(),v1.begin(), std::bind(std::multiplies<int>(), std::placeholders::_1, 2));
for (const auto i : v1)
std::cout << i << " ";
std::cout << std::endl;
return 0;
}
14.43
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<functional>
int main()
{
std::vector<int >v1 = { 2,3,5 };
int v2 = 30;
std::string ret = (std::count_if(v1.begin(), v1.end(), std::bind(std::modulus<int>(), std::placeholders::_1, v2)))
== v1.size() ? "divided" : "not ";
std::cout << ret << std::endl;
return 0;
}
14.44
#include <string>
#include <iostream>
#include <algorithm>
#include <map>
#include<functional>
int add(int i, int j) { return i + j; }
auto mod = [](int i, int j) { return i % j; };
struct divide
{
int operator()(int dividend, int divisor)
{
return dividend / divisor;
}
};
int main()
{
std::map<std::string, std::function<int(int, int)>> binops = {
{"+", add}, //函数指针
{"-", std::minus<int>()}, //标准库函数对象
{"/", divide()}, //用户自定义函数对象
{"*", [](int i, int j) { return i * j; }}, //未命名lambda
{"%", mod} //命名的lambda对象
};
std::cout << binops["+"](10, 5) << std::endl;
std::cout << binops["-"](10, 5) << std::endl;
std::cout << binops["*"](10, 5) << std::endl;
std::cout << binops["/"](10, 5) << std::endl;
std::cout << binops["%"](10, 5) << std::endl;
return 0;
}
14.53
#include <cstddef>
class SmallInt
{
friend SmallInt operator+(const SmallInt& si1, const SmallInt& si2) { SmallInt si_sum(si1.val + si2.val); return si_sum; }
public:
SmallInt(int i = 0) : val(i) {}
operator int() const { return val; }
private:
std::size_t val;
};
int main()
{
SmallInt s1;
//double d = s1 + 3.14;
double d1 = s1 + SmallInt(3.14); //重载+
double d2 = s1.operator int() + 3.14; //内置+
return 0;
}