Skip to content

Instantly share code, notes, and snippets.

@weidonglian
Last active July 16, 2018 12:50
Show Gist options
  • Save weidonglian/cab17a6a1d45e4554c8bddb0e9c7711d to your computer and use it in GitHub Desktop.
Save weidonglian/cab17a6a1d45e4554c8bddb0e9c7711d to your computer and use it in GitHub Desktop.
C++ Collection
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;
}
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();
}
#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';
}
#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'}
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;
}
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.
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.
// 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;
}
#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";
}
}
#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.
};
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