-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
1,381 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#include<iostream> | ||
#include<string> | ||
|
||
template <typename T> | ||
std::ostream & print(std::ostream & os, const T & t) | ||
{ | ||
return os << t; | ||
} | ||
|
||
template <typename T, typename ... Args> | ||
std::ostream & print(std::ostream & os, const T & t, const Args & ... rest) | ||
{ | ||
os << t << ", "; | ||
return print(os, rest...); | ||
} | ||
|
||
int main() | ||
{ | ||
print(std::cout, 1) << std::endl; | ||
print(std::cout, 1, "123") << std::endl; | ||
print(std::cout, 1, "123", 3.123, std::string("qwert"), -5) << std::endl; | ||
return 0; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
#include<iostream> | ||
#include<string> | ||
#include<sstream> | ||
|
||
template <typename T> std::ostream & print(std::ostream & os, const T & t); | ||
template <typename T, typename ... Args> std::ostream & print(std::ostream & os, const T & t, const Args & ... rest); | ||
template <typename T> std::string debug_rep(const T &t); | ||
template <typename T> std::string debug_rep(T * p); | ||
std::string debug_rep(const std::string &s); | ||
std::string debug_rep(char *p); | ||
std::string debug_rep(const char *p); | ||
template <typename ... Args> std::ostream & errorMsg(std::ostream & os, const Args & ... rest); | ||
|
||
template <typename T> | ||
std::ostream & print(std::ostream & os, const T & t) | ||
{ | ||
return os << t; | ||
} | ||
|
||
template <typename T, typename ... Args> | ||
std::ostream & print(std::ostream & os, const T & t, const Args & ... rest) | ||
{ | ||
os << t << ", "; | ||
return print(os, rest...); | ||
} | ||
|
||
template <typename T> | ||
std::string debug_rep(const T &t) | ||
{ | ||
std::ostringstream ret; | ||
ret << t; | ||
return ret.str(); | ||
} | ||
|
||
template <typename T> | ||
std::string debug_rep(T * p) | ||
{ | ||
std::ostringstream ret; | ||
ret << "pointer: " << p; | ||
if(p) | ||
ret << " " << debug_rep(*p); | ||
else | ||
ret << " null pointer"; | ||
return ret.str(); | ||
} | ||
|
||
std::string debug_rep(const std::string &s) | ||
{ | ||
return '"' + s + '"'; | ||
} | ||
|
||
std::string debug_rep(char *p) | ||
{ | ||
return debug_rep(std::string(p)); | ||
} | ||
std::string debug_rep(const char *p) | ||
{ | ||
return debug_rep(std::string(p)); | ||
} | ||
|
||
template <typename ... Args> | ||
std::ostream & errorMsg(std::ostream & os, const Args & ... rest) | ||
{ | ||
return print(os, debug_rep(rest)...); | ||
} | ||
|
||
int main() | ||
{ | ||
int i = 3; | ||
errorMsg(std::cout, 1, "123", std::string("qwer"), &i) << std::endl; | ||
errorMsg(std::cout, 1) << std::endl; | ||
return 0; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
#include<string> | ||
#include<memory> | ||
#include<utility> | ||
#include<algorithm> | ||
#include<utility> | ||
#include<iostream> | ||
#include "StrVec.h" | ||
|
||
std::allocator<std::string> StrVec::alloc; | ||
|
||
void StrVec::push_back(const std::string &s) | ||
{ | ||
chk_n_alloc(); | ||
alloc.construct(first_free++, s); | ||
} | ||
|
||
void StrVec::push_back(std::string &&s) | ||
{ | ||
chk_n_alloc(); | ||
alloc.construct(first_free++, std::move(s)); | ||
} | ||
|
||
std::pair<std::string *, std::string *> StrVec::alloc_n_copy(const std::string *b, const std::string *e) | ||
{ | ||
std::string * data = alloc.allocate(e - b); | ||
return {data, std::uninitialized_copy(b, e, data)}; | ||
} | ||
|
||
void StrVec::free() | ||
{ | ||
if(elements) | ||
{ | ||
StrVec * th = this; | ||
std::for_each(elements, first_free, [](std::string &s){ alloc.destroy(&s); } ); | ||
alloc.deallocate(elements, cap - elements); | ||
} | ||
} | ||
|
||
StrVec::StrVec(const StrVec & s) | ||
{ | ||
std::pair<std::string *, std::string *> newdata = alloc_n_copy(s.begin(), s.end()); | ||
elements = newdata.first; | ||
first_free = cap = newdata.second; | ||
} | ||
|
||
StrVec::~StrVec() | ||
{ | ||
free(); | ||
} | ||
|
||
StrVec & StrVec::operator=(const StrVec & rhs) | ||
{ | ||
std::pair<std::string *, std::string *> data = alloc_n_copy(rhs.begin(), rhs.end()); | ||
free(); | ||
elements = data.first; | ||
first_free = cap = data.second; | ||
return *this; | ||
} | ||
|
||
StrVec & StrVec::operator=(std::initializer_list<std::string> li) | ||
{ | ||
std::pair<std::string *, std::string *> data = alloc_n_copy(li.begin(), li.end()); | ||
free(); | ||
elements = data.first; | ||
first_free = cap = data.second; | ||
return *this; | ||
} | ||
|
||
StrVec::StrVec(std::initializer_list<std::string> li) | ||
{ | ||
std::pair<std::string *, std::string *> newdata = alloc_n_copy(li.begin(), li.end()); | ||
elements = newdata.first; | ||
first_free = cap = newdata.second; | ||
} | ||
|
||
StrVec::StrVec(StrVec &&s) noexcept : elements(s.elements), first_free(s.first_free), cap(s.cap) | ||
{ | ||
s.elements = s.first_free = s.cap = nullptr; | ||
} | ||
|
||
StrVec & 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; | ||
} | ||
|
||
void StrVec::reallocate() | ||
{ | ||
size_t newcapacity = size() ? 2 * size() : 1; | ||
reserve(newcapacity); | ||
} | ||
|
||
void StrVec::reserve(size_t n) | ||
{ | ||
if(n <= capacity()) | ||
return; | ||
std::string * newdata = alloc.allocate(n); | ||
std::string * dest = newdata; | ||
std::string * 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, const std::string &t) | ||
{ | ||
if(n == size()) | ||
return; | ||
if(n < size()) | ||
{ | ||
while(size() != n) | ||
alloc.destroy(--first_free); | ||
return; | ||
} | ||
if(n > capacity()) | ||
reserve(n); | ||
while(size() != n) | ||
alloc.construct(first_free++, t); | ||
} | ||
|
||
bool operator==(const StrVec &lhs, const StrVec &rhs) | ||
{ | ||
if(lhs.size() != rhs.size()) | ||
return false; | ||
for(const std::string *p1 = lhs.begin(), *p2 = rhs.begin(); p1 != lhs.end(); ++p1, ++p2) | ||
if(*p1 != *p2) | ||
return false; | ||
return true; | ||
} | ||
|
||
bool operator!=(const StrVec &lhs, const StrVec &rhs) | ||
{ | ||
return !(lhs == rhs); | ||
} | ||
|
||
bool operator<(const StrVec &lhs, const StrVec &rhs) | ||
{ | ||
const std::string *p1 = lhs.begin(), *p2 = rhs.begin(); | ||
for( ; p1 != lhs.end() && p2 != rhs.end(); ++p1, ++p2) | ||
{ | ||
if(*p1 < *p2) | ||
return true; | ||
if(*p1 > *p2) | ||
return false; | ||
} | ||
if(p1 != lhs.end() && p2 == rhs.end()) | ||
return false; | ||
if(p1 == lhs.end() && p2 != rhs.end()) | ||
return true; | ||
return false; | ||
} | ||
|
||
bool operator<=(const StrVec &lhs, const StrVec &rhs) | ||
{ | ||
return !(lhs > rhs); | ||
} | ||
|
||
bool operator>(const StrVec &lhs, const StrVec &rhs) | ||
{ | ||
const std::string *p1 = lhs.begin(), *p2 = rhs.begin(); | ||
for( ; p1 != lhs.end() && p2 != rhs.end(); ++p1, ++p2) | ||
{ | ||
if(*p1 > *p2) | ||
return true; | ||
if(*p1 < *p2) | ||
return false; | ||
} | ||
if(p1 != lhs.end() && p2 == rhs.end()) | ||
return true; | ||
if(p1 == lhs.end() && p2 != rhs.end()) | ||
return false; | ||
return false; | ||
} | ||
|
||
bool operator>=(const StrVec &lhs, const StrVec &rhs) | ||
{ | ||
return !(lhs < rhs); | ||
} | ||
|
||
std::string & StrVec::operator[](std::size_t n) | ||
{ | ||
return elements[n]; | ||
} | ||
|
||
const std::string & StrVec::operator[](std::size_t n) const | ||
{ | ||
return elements[n]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
#ifndef STRVEC_H | ||
#define STRVEC_H | ||
|
||
#include<string> | ||
#include<memory> | ||
#include<utility> | ||
#include<initializer_list> | ||
|
||
class StrVec | ||
{ | ||
friend bool operator==(const StrVec &lhs, const StrVec &rhs); | ||
friend bool operator<(const StrVec &lhs, const StrVec &rhs); | ||
friend bool operator>(const StrVec &lhs, const StrVec &rhs); | ||
public: | ||
|
||
StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) { } | ||
StrVec(const StrVec &); | ||
StrVec & operator=(const StrVec &); | ||
~StrVec(); | ||
StrVec(std::initializer_list<std::string> li); | ||
|
||
StrVec(StrVec &&s) noexcept; | ||
StrVec & operator=(StrVec &&rhs) noexcept; | ||
StrVec & operator=(std::initializer_list<std::string> li); | ||
|
||
std::string & operator[](std::size_t n); | ||
const std::string & operator[](std::size_t n) const; | ||
|
||
void push_back(const std::string &); | ||
void push_back(std::string &&); | ||
template <typename ... Args> void emplace_back(Args && ... args); | ||
|
||
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); | ||
void resize(size_t n, const std::string &t = std::string()); | ||
private: | ||
|
||
static 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; | ||
}; | ||
|
||
bool operator==(const StrVec &lhs, const StrVec &rhs); | ||
bool operator!=(const StrVec &lhs, const StrVec &rhs); | ||
bool operator<(const StrVec &lhs, const StrVec &rhs); | ||
bool operator<=(const StrVec &lhs, const StrVec &rhs); | ||
bool operator>(const StrVec &lhs, const StrVec &rhs); | ||
bool operator>=(const StrVec &lhs, const StrVec &rhs); | ||
|
||
|
||
template <typename ... Args> | ||
void StrVec::emplace_back(Args && ... args) | ||
{ | ||
chk_n_alloc(); | ||
alloc.construct(first_free++, std::forward<Args>(args)...); | ||
} | ||
|
||
#endif |
Oops, something went wrong.