Last active
July 16, 2018 12:50
-
-
Save weidonglian/cab17a6a1d45e4554c8bddb0e9c7711d to your computer and use it in GitHub Desktop.
C++ Collection
This file contains hidden or 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
template <class T, class TAlloc> | |
class FlVecAllocator { | |
public: | |
template <typename U> | |
using rebind = FlVecAllocator<U, TAlloc>; | |
using value_type = T; | |
using pointer = value_type *; | |
FlVecAllocator() noexcept = default; | |
template <class U> | |
FlVecAllocator(const FlVecAllocator<U, TAlloc>&) noexcept { | |
} | |
pointer allocate(std::size_t n) { | |
std::cerr << "++++++++++Allocating:" << n << std::endl; | |
return m_proxyAllocator.allocate(n); | |
} | |
void deallocate(pointer p, std::size_t n) noexcept // Use pointer if pointer is not a value_type* | |
{ | |
std::cerr << "----------Deallocating:" << p << ", " << n << std::endl; | |
m_proxyAllocator.deallocate(p, n); | |
} | |
private: | |
TAlloc m_proxyAllocator; | |
}; | |
template< class T1, class TAlloc1, class T2, class TAlloc2> | |
bool operator==(const FlVecAllocator<T1, TAlloc1>& lhs, const FlVecAllocator<T2, TAlloc2>& rhs) { | |
return true; | |
} |
This file contains hidden or 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
int i = 5; | |
auto a1 = i; // value | |
auto & a2 = i; // reference | |
#include <typeinfo> | |
#include <iostream> | |
template<typename T> | |
struct A { | |
static void foo() { | |
std::cout << "value" << std::endl; | |
} | |
}; | |
template<typename T> | |
struct A<T&> { | |
static void foo() { | |
std::cout << "reference" << std::endl; | |
} | |
}; | |
float& bar() { | |
static float t = 5.5; | |
return t; | |
}; | |
int main() { | |
int i = 5; | |
int &r = i; | |
auto a1 = i; | |
auto a2 = r; | |
auto a3 = bar(); | |
A<decltype(i)>::foo(); | |
A<decltype(r)>::foo(); | |
A<decltype(a1)>::foo(); | |
A<decltype(a2)>::foo(); | |
A<decltype(bar())>::foo(); | |
A<decltype(a3)>::foo(); | |
} |
This file contains hidden or 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
#include <iostream> | |
#include <iomanip> | |
#include <chrono> | |
std::ostream& | |
display(std::ostream& os, std::chrono::nanoseconds ns) | |
{ | |
using namespace std; | |
using namespace std::chrono; | |
typedef duration<int, ratio<86400>> days; | |
char fill = os.fill(); | |
os.fill('0'); | |
auto d = duration_cast<days>(ns); | |
ns -= d; | |
auto h = duration_cast<hours>(ns); | |
ns -= h; | |
auto m = duration_cast<minutes>(ns); | |
ns -= m; | |
auto s = duration_cast<seconds>(ns); | |
os << setw(2) << d.count() << "d:" | |
<< setw(2) << h.count() << "h:" | |
<< setw(2) << m.count() << "m:" | |
<< setw(2) << s.count() << 's'; | |
os.fill(fill); | |
return os; | |
}; | |
int | |
main() | |
{ | |
std::cout << "Operation took "; | |
display(std::cout, std::chrono::microseconds(918734000000)); | |
std::cout << '\n'; | |
} |
This file contains hidden or 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
#include <algorithm> | |
//C++11 code | |
//are all of the elements positive? | |
all_of(first, first+n, ispositive()); //false | |
//is there at least one positive element? | |
any_of(first, first+n, ispositive());//true | |
// are none of the elements positive? | |
none_of(first, first+n, ispositive()); //false | |
//A new category of copy_n algorithms is also available. Using copy_n(), copying an array of 5 elements to another array is a cinch: | |
int source[5]={0,12,34,50,80}; | |
int target[5]; | |
//copy 5 elements from source to target | |
copy_n(source,5,target); | |
include <numeric> | |
int a[5]={0}; | |
char c[3]={0}; | |
iota(a, a+5, 10); //changes a to {10,11,12,13,14} | |
iota(c, c+3, 'a'); //{'a','b','c'} |
This file contains hidden or 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
std::vector<std::future<int>> futures; | |
for(int i = 0; i < 10; ++i) | |
futures.push_back (std::async([](int m) {return 2 * m;} , i)); | |
for(auto &e : futures) { | |
std::cout << e.get() << std::endl; | |
} |
This file contains hidden or 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
std::distance(itBeg, itEnd); | |
std::unorded_map; | |
std::future | |
std::chrono | |
auto | |
lambda [](){} | |
constexpr // better for compile programing | |
std::initializer_list | |
std::uninitialized_copy // new(ptr) T; | |
std::array | |
std::vector<int> vec; for (int i : vec) {} or for (auto i: vec) {}; for (auto& i: vec) {} | |
std::valarray<> | |
nullptr | |
enum Weather: std::uint8_t { sunny, rainy, cloudy, foggy }; // define underlying type | |
enum class Voltage {low, high}; // scoped enum string type | |
std::char16_t = u'x', std::char32_t = U'x'; | |
std::string, std::wstring, std::u16string, std::u32string; | |
std::wbuffer_convert and std::wstring_convert; | |
std::regex support now. |
This file contains hidden or 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
using namespace std; // import all the names in std. Not recommended | |
using namespace boost; // import all the names in boost. Not recommended. | |
using std::string; // import only the specific name 'std::string'. Prefered in source file. | |
namespace po = boost::program_options; // redefine a new namespace from existing one. |
This file contains hidden or 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
// operator new example | |
#include <iostream> // std::cout | |
#include <new> // ::operator new | |
struct MyClass { | |
int data[100]; | |
MyClass() {std::cout << "constructed [" << this << "]\n";} | |
~MyClass() { std::cout << "++deconstructed [" << this << "]\n";} | |
}; | |
int main () { | |
std::cout << "1: "; | |
MyClass * p1 = new MyClass; | |
// allocates memory by calling: operator new (sizeof(MyClass)) | |
// and then constructs an object at the newly allocated space | |
std::cout << "2: "; | |
MyClass * p2 = new (std::nothrow) MyClass; | |
// allocates memory by calling: operator new (sizeof(MyClass),std::nothrow) | |
// and then constructs an object at the newly allocated space | |
p2->~MyClass(); | |
std::cout << "3: "; | |
new (p2) MyClass; | |
// does not allocate memory -- calls: operator new (sizeof(MyClass),p2) | |
// but constructs an object at p2 | |
// Notice though that calling this function directly does not construct an object: | |
std::cout << "4: \n"; | |
MyClass * p3 = (MyClass*) ::operator new (sizeof(MyClass)); | |
// allocates memory by calling: operator new (sizeof(MyClass)) | |
// but does not call MyClass's constructor | |
delete p1; | |
delete p2; | |
delete p3; | |
return 0; | |
} |
This file contains hidden or 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
#include <iostream> | |
#include <typeinfo> | |
#include <deque> | |
#include <map> | |
#include <cassert> | |
using namespace std; | |
struct ObjectDatabase { | |
ObjectDatabase() { } | |
template<typename T> | |
T &allocate() { | |
deque<T> &a = getObjects<T>(); | |
a.push_back(T()); | |
return a.back(); | |
} | |
template<typename T> | |
deque<T> &getObjects() { | |
CollectionBase *&el = m_obdb[typeid(T).name()]; | |
if ( not el ) | |
el = new Collection<T>(); | |
Collection<T> *elc = dynamic_cast<Collection<T>*>(el); | |
assert(elc); | |
deque<T> &a = elc->elements; | |
return a; | |
} | |
~ObjectDatabase() { | |
for ( ObDB::iterator i=m_obdb.begin(); i!=m_obdb.end(); ++i) | |
delete i->second; | |
} | |
private: | |
ObjectDatabase(ObjectDatabase const &); | |
ObjectDatabase &operator=(ObjectDatabase const &); | |
struct CollectionBase { | |
virtual ~CollectionBase() { } | |
}; | |
template<typename T> | |
struct Collection : CollectionBase { | |
deque<T> elements; | |
}; | |
typedef map<string, CollectionBase *> ObDB; | |
ObDB m_obdb; | |
}; | |
struct Foo { | |
Foo() : name("Generic Foo") { } | |
char const *name; | |
}; | |
struct Bar { | |
string name; | |
}; | |
int main() { | |
ObjectDatabase obdb; | |
obdb.allocate<Foo>().name = "My First Foo"; | |
obdb.allocate<Bar>().name = "My First Bar"; | |
{ | |
Foo &f = obdb.allocate<Foo>(); | |
f.name = "My Second Foo"; | |
Bar &b = obdb.allocate<Bar>(); | |
b.name = "My Second Bar"; | |
} | |
obdb.allocate<Foo>(); | |
obdb.allocate<Bar>(); | |
{ | |
cout << "Printing Foo Names\n"; | |
deque<Foo> &foos = obdb.getObjects<Foo>(); | |
for ( deque<Foo>::iterator i = foos.begin(); i!=foos.end(); ++i ) | |
cout << " -> " << i->name << "\n"; | |
} | |
{ | |
cout << "Printing Bar Names\n"; | |
deque<Bar> &bars = obdb.getObjects<Bar>(); | |
for ( deque<Bar>::iterator i = bars.begin(); i!=bars.end(); ++i ) | |
cout << " -> " << i->name << "\n"; | |
} | |
} |
This file contains hidden or 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
#include <algorithm> // std::equal | |
#include <stdexcept> // std::out_of_range | |
#include <type_traits> // std::is_trivially_destructible | |
#include <initializer_list> | |
#include <cstdio> // size_t, printf | |
// | |
// Based on | |
// http://codereview.stackexchange.com/questions/123402/c-vector-the-basics | |
// http://lokiastari.com/blog/2016/03/19/vector-simple-optimizations/ | |
// | |
template<typename T, size_t SIZE> | |
class SmallVector{ | |
private: | |
static constexpr bool DEBUG_ = true; | |
public: | |
// TYPES | |
using value_type = T; | |
using size_type = size_t; | |
using iterator = value_type *; | |
using const_iterator = const value_type *; | |
private: | |
size_type length = 0; | |
char arena[ SIZE * sizeof(value_type) ]; | |
public: | |
// STANDARD C-TORS | |
SmallVector() = default; | |
SmallVector(const SmallVector &other){ | |
appendCopy(std::begin(other), std::end(other)); | |
log__("Copy C-Tor"); | |
} | |
SmallVector(SmallVector &&other){ | |
appendMove(std::begin(other), std::end(other)); | |
other.length = 0; | |
log__("Move C-Tor"); | |
} | |
SmallVector &operator=(const SmallVector &other){ | |
clear(); | |
appendCopy(std::begin(other), std::end(other)); | |
log__("Copy Assign"); | |
return *this; | |
} | |
SmallVector &operator=(SmallVector &&other){ | |
clear(); | |
appendMove(std::begin(other), std::end(other)); | |
other.length = 0; | |
log__("Move Assign"); | |
return *this; | |
} | |
// OTHER C-TORS | |
template<class IT> | |
SmallVector(IT begin, IT end){ | |
appendCopy(begin, end); | |
log__("Iterator C-Tor"); | |
} | |
SmallVector(const std::initializer_list<T> & list) : | |
SmallVector(std::begin(list), std::end(list)){ | |
log__("Initializer C-Tor"); | |
} | |
// D-TOR | |
~SmallVector(){ | |
destructAll_<value_type>(cbegin(), cend()); | |
} | |
// MUTATIONS | |
void clear(){ | |
destructAll_<value_type>(cbegin(), cend()); | |
length = 0; | |
} | |
void push_back(const value_type &value){ | |
placeBack_(value); | |
} | |
void push_back(value_type &&value){ | |
placeBack_(std::move(value)); | |
} | |
template<typename... Args> | |
void emplace_back(Args&&... args){ | |
placeBack_(std::forward<Args>(args)...); | |
} | |
void pop_back() noexcept{ | |
// see [1] | |
--length; | |
destruct_<value_type>( data_(length) ); | |
} | |
// COMPARISSON | |
template<typename CONTAINER> | |
bool operator==(const CONTAINER &other) const noexcept{ | |
return equals_(other); | |
} | |
template<typename CONTAINER> | |
bool operator!=(const CONTAINER &other) const noexcept{ | |
return ! equals_(other); | |
} | |
// ITERATORS | |
iterator begin() noexcept{ | |
return data_(); | |
} | |
iterator end() noexcept{ | |
return data_() + length; | |
} | |
// CONST ITERATORS | |
const_iterator begin() const noexcept{ | |
return data_(); | |
} | |
const_iterator end() const noexcept{ | |
return data_() + length; | |
} | |
// C++11 CONST ITERATORS | |
const_iterator cbegin() const noexcept{ | |
return begin(); | |
} | |
const_iterator cend() const noexcept{ | |
return end(); | |
} | |
// SIZE | |
constexpr size_type size() const noexcept{ | |
return length; | |
} | |
constexpr bool empty() const noexcept{ | |
return size() == 0; | |
} | |
// MORE SIZE | |
static void reserve(size_type const){ | |
// left for compatibility | |
} | |
constexpr static size_type capacity(){ | |
return SIZE; | |
} | |
constexpr static size_type max_size(){ | |
return SIZE; | |
} | |
// DATA | |
value_type *data() noexcept{ | |
return data_(); | |
} | |
const value_type *data() const noexcept{ | |
return data_(); | |
} | |
// ACCESS WITH RANGE CHECK | |
value_type &at(size_type const index){ | |
validateIndex_(index); | |
return data_(index); | |
} | |
const value_type &at(size_type const index) const{ | |
validateIndex_(index); | |
return data_(index); | |
} | |
// ACCESS WITHOUT RANGE CHECK | |
value_type &operator[](size_type const index) noexcept{ | |
// see [1] behavior is undefined | |
return data_(index); | |
} | |
const value_type &operator[](size_type const index) const noexcept{ | |
// see [1] behavior is undefined | |
return data_(index); | |
} | |
// FRONT | |
value_type &front() noexcept{ | |
// see [1] behavior is undefined | |
return data_(0); | |
} | |
const value_type &front() const noexcept{ | |
// see [1] behavior is undefined | |
return data_(0); | |
} | |
// BACK | |
value_type &back() noexcept{ | |
// see [1] behavior is undefined | |
return data_(length - 1); | |
} | |
const value_type &back() const noexcept{ | |
// see [1] behavior is undefined | |
return data_(length - 1); | |
} | |
public: | |
// NON STANDARD APPEND | |
template<class IT> | |
void appendCopy(IT begin, IT end){ | |
for(auto it = begin; it != end; ++it) | |
push_back(*it); | |
} | |
template<class IT> | |
void appendMove(IT begin, IT end){ | |
for(auto it = begin; it != end; ++it) | |
push_back(std::move(*it)); | |
} | |
private: | |
template<typename... Args> | |
void placeBack_(Args&&... args){ | |
if (length >= SIZE){ | |
std::bad_alloc exception; | |
throw exception; | |
} | |
void *placement = data_() + length; | |
new(placement) value_type(std::forward<Args>(args)...); | |
++length; | |
} | |
template<typename CONTAINER> | |
bool equals_(const CONTAINER &other) const noexcept{ | |
return length == other.length | |
? std::equal(begin(), end(), other.begin()) | |
: false; | |
} | |
void validateIndex_(size_type const index) const{ | |
if (index >= length){ | |
std::out_of_range exception("Out of Range"); | |
throw exception; | |
} | |
} | |
private: | |
// LOW LEVEL DATA ACCESS | |
T *data_() noexcept{ | |
return reinterpret_cast<T *>(arena); | |
} | |
const T *data_() const noexcept{ | |
return reinterpret_cast<const T *>(const_cast<char *>(arena)); | |
} | |
T &data_(size_type const index) noexcept{ | |
return data_() [index]; | |
} | |
const T &data_(size_type const index) const noexcept{ | |
return data_() [index]; | |
} | |
private: | |
// TRIVIAL DESTRUCTOR | |
template<typename X> | |
typename std::enable_if<std::is_trivially_destructible<X>::value == true>::type | |
static destruct_(const T &){ | |
// Trivially destructible objects can be re-used without using the destructor. | |
} | |
template<typename X, class IT> | |
typename std::enable_if<std::is_trivially_destructible<X>::value == true>::type | |
static destructAll_(const IT, const IT){ | |
// Trivially destructible objects can be re-used without using the destructor. | |
} | |
// NORMAL DESTRUCTOR | |
template<typename X> | |
typename std::enable_if<std::is_trivially_destructible<X>::value == false>::type | |
static destruct_(const T &t){ | |
t.~T(); | |
} | |
template<typename X, class IT> | |
typename std::enable_if<std::is_trivially_destructible<X>::value == false>::type | |
static destructAll_(IT begin, IT end){ | |
for(auto it = begin; it != end; ++it) | |
destruct_<value_type>(*it); | |
} | |
private: | |
void log__(const char *msg) const noexcept{ | |
if (DEBUG_) | |
printf("%-20s size: %5zu\n", msg, length); | |
} | |
void swap(SmallVector& other) noexcept{ | |
using std::swap; | |
swap(length, other.length ); | |
swap(arena, other.arena ); | |
} | |
// Remark [1] | |
// | |
// If the container is not empty, | |
// the function never throws exceptions (no-throw guarantee). | |
// Otherwise, it causes undefined behavior. | |
}; |
This file contains hidden or 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
struct pod_tag {}; | |
struct non_pod_tag {}; | |
template<class T> struct copy_trait { using tag = non_pod_tag; }; // T is not "plain old data" | |
template<> struct copy_trait<int> { using tag = pod_tag; }; // int is "plain old data" | |
template<class Iter> | |
Out copy_helper(Iter first, Iter last, Iter out, pod_tag) | |
{ | |
// use memmove | |
} | |
template<class Iter> | |
Out copy_helper(Iter first, Iter last, Iter out, non_pod_tag) | |
{ | |
// use loop calling copy constructors | |
} | |
template<class Itert> | |
Out copy(Iter first, Iter last, Iter out) | |
{ | |
return copy_helper(first, last, out, typename copy_trait<Iter>::tag{}) | |
} | |
void use(vector<int>& vi, vector<int>& vi2, vector<string>& vs, vector<string>& vs2) | |
{ | |
copy(vi.begin(), vi.end(), vi2.begin()); // uses memmove | |
copy(vs.begin(), vs.end(), vs2.begin()); // uses a loop calling copy constructors | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment