Last active
January 15, 2024 10:26
-
-
Save Stanley00/ef8151502a93deefe4fa to your computer and use it in GitHub Desktop.
C++ small code snip
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
#include <stdio.h> | |
#include <stdlib.h> | |
#define DECLARE(...) for(__VA_ARGS__ | |
#define DECLARE_CHECK(...) __VA_ARGS__ | |
#define DEFER(...) __VA_ARGS__) | |
#define DEFER_BREAK continue | |
int main(void) | |
{ | |
DECLARE(int *p) = malloc(10*sizeof(*p)); | |
DECLARE_CHECK(p); | |
DEFER(free(p), p=NULL, printf("Free p\n")){ | |
DECLARE(int *q)=malloc(10*sizeof(*q)); | |
DECLARE_CHECK(q); | |
DEFER(free(q), q=NULL, printf("Free q\n")){ | |
printf("Yay\n"); | |
DEFER_BREAK; | |
printf("No\n"); | |
} | |
printf("Yuck\n"); | |
} | |
return EXIT_SUCCESS; | |
} |
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
#include <stdio.h> | |
struct range | |
{ | |
int from; | |
int to; | |
int step; | |
}; | |
#define range(...) range((struct range){.from=1,.to=10,.step=1, __VA_ARGS__}) | |
int sign(int n) | |
{ | |
if (n<0) | |
{ | |
return -1; | |
} | |
return 1; | |
} | |
/* use parentheses to avoid macro subst */ | |
void (range)(struct range r) | |
{ | |
int i; | |
if ((r.to-r.from)*r.step<0) | |
{ | |
r.step*=-1; | |
} | |
for (i = r.from; i*sign(r.step) <= r.to*sign(r.step); i += r.step) | |
{ | |
printf("%d ", i); | |
} | |
puts(""); | |
} | |
int main() | |
{ | |
range(); | |
range(.from=2, .to=4); | |
range(.from=10, .to=2); | |
range(.step=2); | |
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
size_t count_utf8_char(const std::string& s) | |
{ | |
size_t count = 0; | |
for (const unsigned char p : s) | |
{ | |
if ( (p&0x80)==0 || (p&0xc0)==0xc0) | |
count++; | |
} | |
return count; | |
} |
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
#include <iostream> | |
using namespace std; | |
#define BARK std::cout << __PRETTY_FUNCTION__ << '\n' | |
template <class Z, class X> | |
struct Y | |
{ | |
auto operator ->() const | |
{ | |
return &z; | |
} | |
auto operator ->() | |
{ | |
return &z; | |
} | |
private: | |
~Y() = default; | |
friend X; | |
Z z; | |
}; | |
struct Z | |
{ | |
void f() | |
{ | |
BARK; | |
} | |
}; | |
struct X | |
{ | |
auto& get() | |
{ | |
return y; | |
} | |
private: | |
Y<Z, X> y; | |
}; | |
int main() | |
{ | |
X x; | |
x.get()->f(); | |
//auto y = x.get(); // error | |
} |
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
#include <iostream> | |
// This cannot be used for rvalue array | |
// And make sure you pass const ref to both functions | |
template <typename T, size_t N> constexpr size_t count_of (const T (&a)[N]){return N;} | |
template <typename T, size_t N> constexpr size_t test(const T (&a)[N]){ return count_of(a);} | |
int main() | |
{ | |
int a[]={1,2,3,4,5}; | |
int b[]={1,2,3,4,5,6,7,8}; | |
// Should output: 5 8 | |
std::cout << test(a) << "\n" << test(b) << "\n"; | |
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
#include <iostream> | |
#include <functional> | |
#include <optional> | |
#define BARK do {std::cout << __PRETTY_FUNCTION__ << '\n';} while(0) | |
void f(){ | |
BARK; | |
} | |
using Callback = void (*)(void); | |
auto call(Callback f){ | |
return f(); | |
} | |
void g(int i){ | |
std::cout << i << " from "; BARK; | |
} | |
template<auto cb, class... Ts> | |
constexpr auto make_void_cb(Ts&&... ds){ | |
static std::optional<std::tuple<Ts...>> d; | |
if (d) throw d; | |
d = std::make_tuple(std::forward<Ts>(ds)...); | |
struct XX{ | |
static void f(){ | |
std::apply(cb, *d); | |
d = std::nullopt; | |
} | |
}; | |
return &XX::f; | |
} | |
int main() | |
{ | |
call(f); | |
call(make_void_cb<g>(42)); | |
call(make_void_cb<g>(47)); | |
} |
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
#include <iostream> | |
#include <iomanip> | |
#include <vector> | |
constexpr auto POW(unsigned long long base, unsigned exp){ | |
auto r = base; | |
while(--exp){ | |
r *= base; | |
} | |
return r; | |
} | |
struct BigNum{ | |
BigNum(unsigned long long n): data_{{n}}{} | |
bool operator<(const BigNum& o) const{ | |
if (data_.size()<o.data_.size()) return true; | |
if (data_.size()>o.data_.size()) return false; | |
for (auto li=data_.rbegin(), ri=o.data_.rbegin(); li!=data_.rend(); ++li, ++ri){ | |
if (*li < *ri) return true; | |
if (*li > *ri) return false; | |
} | |
return false; | |
} | |
auto operator[](size_t i) const { | |
return (i<data_.size())?data_[i]:0; | |
} | |
BigNum& operator+=(const BigNum& o){ | |
unsigned long long carry = 0; | |
const auto max_len = std::max(data_.size(), o.data_.size()); | |
for (size_t i=0; i<max_len; ++i){ | |
data_[i] = (*this)[i] + o[i] + carry; | |
carry = data_[i]/BASE; | |
data_[i] %= BASE; | |
} | |
while (carry>0){ | |
data_.push_back(carry%BASE); | |
carry /= BASE; | |
} | |
return *this; | |
} | |
BigNum& operator*=(unsigned long long n){ | |
unsigned long long carry = 0; | |
for (size_t i=0; i<data_.size(); ++i){ | |
data_[i] = (*this)[i]*n+carry; | |
carry = data_[i]/BASE; | |
data_[i] %= BASE; | |
} | |
while (carry>0){ | |
data_.push_back(carry%BASE); | |
carry /= BASE; | |
} | |
return *this; | |
} | |
private: | |
static constexpr unsigned BASE_WIDTH = 9; | |
static constexpr unsigned long long BASE = POW(10, BASE_WIDTH); | |
std::vector<unsigned long long> data_; | |
friend decltype(auto) operator<<(std::ostream&, const BigNum&); | |
}; | |
decltype(auto) operator<<(std::ostream& os, const BigNum& n){ | |
os << *rbegin(n.data_); | |
for (auto i=next(rbegin(n.data_)); i<rend(n.data_); ++i) | |
os << std::setfill('0') << std::setw(n.BASE_WIDTH) << *i; | |
return os; | |
} | |
int main() | |
{ | |
BigNum n = 1; | |
for (int i=1; i<100; ++i){ | |
n*=i; | |
std::cout << n << '\n'; | |
} | |
n += n; | |
std::cout << 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
// Idea got from https://verdagon.dev/blog/on-removing-let-let-mut | |
// Require C++17 | |
#include <iostream> | |
template<class T> | |
struct let_assign; | |
template<class T> | |
struct let{ | |
let(const T& a):d{a}{} | |
template<class X> | |
let& operator=(X&&){ | |
static_assert(sizeof(X)==0, "Must use let_assign to assign"); return *this; | |
} | |
operator const T&() const{ | |
return d; | |
} | |
friend struct let_assign<T>; | |
private: | |
T d={}; | |
}; | |
template<class T> | |
struct let_assign{ | |
let_assign(let<T>& x):x{x}{}; | |
decltype(auto) operator=(int a){ | |
x.d = a; | |
return *this; | |
} | |
private: | |
let<T>& x; | |
}; | |
template<class T> | |
let_assign(let<T>&) -> let_assign<T>; | |
int main() { | |
let x = 10; | |
//x = 20; // Error, must use `let_assign` "keyword" | |
let_assign {x} = 42; | |
std::cout << x << '\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
template <class> | |
struct Succ; | |
struct Zero; | |
template<unsigned> | |
struct Num_; | |
template<unsigned n> | |
using Num = Num_<n>::val; | |
template<> | |
struct Num_<0>{ | |
using val = Zero; | |
}; | |
template<unsigned n> | |
struct Num_{ | |
using val = Succ<Num<n-1>>; | |
}; | |
template <class, class> | |
struct Add_; | |
template <class U, class V> | |
using Add = typename Add_<U, V>::type; | |
template <class T> | |
struct Add_<Zero, T>{ | |
using type = T; | |
}; | |
template <class T, class U> | |
struct Add_<Succ<T>, U>{ | |
using type = Succ<Add<T, U>>; | |
}; | |
template <class> | |
constexpr bool always_false = false; | |
template <class T, class> | |
struct Same{ | |
static_assert(always_false<T>, "Proof failed"); | |
}; | |
template<class T> | |
struct Same<T, T>{}; | |
using Four = Num<4>; | |
using Two = Num<2>; | |
constexpr auto Proof = Same<Add<Two, Two>, Four>{}; |
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
#include <vector> | |
#include <array> | |
#include <stdexcept> | |
namespace nonstd | |
{ | |
template <class T, size_t Size> | |
struct StackAllocator { | |
public: | |
using value_type = T; | |
using size_type = std::size_t; | |
using difference_type = std::ptrdiff_t; | |
using propagate_on_container_move_assignment = std::false_type; | |
using is_always_equal = std::false_type; | |
[[nodiscard]] T* allocate(std::size_t n) | |
{ | |
if ((n > Size) || (c_[1] > 0)) { | |
throw std::bad_alloc(); | |
} | |
if (c_[0]==0) { | |
c_[0] = n; | |
} else { | |
c_[1] = n; | |
} | |
return &m_[0]; | |
} | |
size_type max_size() const | |
{ | |
return Size; | |
} | |
void deallocate(T*, std::size_t n) noexcept | |
{ | |
if (n==c_[0]) { | |
c_[0] = c_[1]; | |
c_[1] = 0; | |
} | |
} | |
private: | |
std::array<T, Size> m_; | |
size_type c_[2] = {}; | |
}; | |
template <class T, class U, std::size_t SizeT, std::size_t SizeU> | |
bool operator==(const StackAllocator<T, SizeT>& t, const StackAllocator<U, SizeU>& u) | |
{ | |
return &t == &u; | |
} | |
template <class T, class U, std::size_t SizeT, std::size_t SizeU> | |
bool operator!=(const StackAllocator<T, SizeT>& t, const StackAllocator<U, SizeU>& u) | |
{ | |
return !(t==u); | |
} | |
template<class T, std::size_t Size> | |
using stack_vector = std::vector<T, StackAllocator<T, Size>>; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment